diff options
Diffstat (limited to 'drivers/usb/host/ohci-hcd.c')
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 64 |
1 files changed, 45 insertions, 19 deletions
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 94d8cf4b36c1..1027aa04583d 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -88,7 +88,7 @@ | |||
88 | #include <linux/timer.h> | 88 | #include <linux/timer.h> |
89 | #include <linux/list.h> | 89 | #include <linux/list.h> |
90 | #include <linux/usb.h> | 90 | #include <linux/usb.h> |
91 | #include <linux/usb_otg.h> | 91 | #include <linux/usb/otg.h> |
92 | #include <linux/dma-mapping.h> | 92 | #include <linux/dma-mapping.h> |
93 | #include <linux/dmapool.h> | 93 | #include <linux/dmapool.h> |
94 | #include <linux/reboot.h> | 94 | #include <linux/reboot.h> |
@@ -101,7 +101,7 @@ | |||
101 | 101 | ||
102 | #include "../core/hcd.h" | 102 | #include "../core/hcd.h" |
103 | 103 | ||
104 | #define DRIVER_VERSION "2005 April 22" | 104 | #define DRIVER_VERSION "2006 August 04" |
105 | #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" | 105 | #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" |
106 | #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" | 106 | #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" |
107 | 107 | ||
@@ -110,9 +110,10 @@ | |||
110 | #undef OHCI_VERBOSE_DEBUG /* not always helpful */ | 110 | #undef OHCI_VERBOSE_DEBUG /* not always helpful */ |
111 | 111 | ||
112 | /* For initializing controller (mask in an HCFS mode too) */ | 112 | /* For initializing controller (mask in an HCFS mode too) */ |
113 | #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR | 113 | #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR |
114 | #define OHCI_INTR_INIT \ | 114 | #define OHCI_INTR_INIT \ |
115 | (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH) | 115 | (OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_UE \ |
116 | | OHCI_INTR_RD | OHCI_INTR_WDH) | ||
116 | 117 | ||
117 | #ifdef __hppa__ | 118 | #ifdef __hppa__ |
118 | /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ | 119 | /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ |
@@ -128,12 +129,13 @@ | |||
128 | 129 | ||
129 | static const char hcd_name [] = "ohci_hcd"; | 130 | static const char hcd_name [] = "ohci_hcd"; |
130 | 131 | ||
132 | #define STATECHANGE_DELAY msecs_to_jiffies(300) | ||
133 | |||
131 | #include "ohci.h" | 134 | #include "ohci.h" |
132 | 135 | ||
133 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); | 136 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); |
134 | static int ohci_init (struct ohci_hcd *ohci); | 137 | static int ohci_init (struct ohci_hcd *ohci); |
135 | static void ohci_stop (struct usb_hcd *hcd); | 138 | static void ohci_stop (struct usb_hcd *hcd); |
136 | static int ohci_reboot (struct notifier_block *, unsigned long , void *); | ||
137 | 139 | ||
138 | #include "ohci-hub.c" | 140 | #include "ohci-hub.c" |
139 | #include "ohci-dbg.c" | 141 | #include "ohci-dbg.c" |
@@ -416,21 +418,20 @@ static void ohci_usb_reset (struct ohci_hcd *ohci) | |||
416 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 418 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
417 | } | 419 | } |
418 | 420 | ||
419 | /* reboot notifier forcibly disables IRQs and DMA, helping kexec and | 421 | /* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and |
420 | * other cases where the next software may expect clean state from the | 422 | * other cases where the next software may expect clean state from the |
421 | * "firmware". this is bus-neutral, unlike shutdown() methods. | 423 | * "firmware". this is bus-neutral, unlike shutdown() methods. |
422 | */ | 424 | */ |
423 | static int | 425 | static void |
424 | ohci_reboot (struct notifier_block *block, unsigned long code, void *null) | 426 | ohci_shutdown (struct usb_hcd *hcd) |
425 | { | 427 | { |
426 | struct ohci_hcd *ohci; | 428 | struct ohci_hcd *ohci; |
427 | 429 | ||
428 | ohci = container_of (block, struct ohci_hcd, reboot_notifier); | 430 | ohci = hcd_to_ohci (hcd); |
429 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | 431 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); |
430 | ohci_usb_reset (ohci); | 432 | ohci_usb_reset (ohci); |
431 | /* flush the writes */ | 433 | /* flush the writes */ |
432 | (void) ohci_readl (ohci, &ohci->regs->control); | 434 | (void) ohci_readl (ohci, &ohci->regs->control); |
433 | return 0; | ||
434 | } | 435 | } |
435 | 436 | ||
436 | /*-------------------------------------------------------------------------* | 437 | /*-------------------------------------------------------------------------* |
@@ -446,7 +447,6 @@ static int ohci_init (struct ohci_hcd *ohci) | |||
446 | 447 | ||
447 | disable (ohci); | 448 | disable (ohci); |
448 | ohci->regs = hcd->regs; | 449 | ohci->regs = hcd->regs; |
449 | ohci->next_statechange = jiffies; | ||
450 | 450 | ||
451 | /* REVISIT this BIOS handshake is now moved into PCI "quirks", and | 451 | /* REVISIT this BIOS handshake is now moved into PCI "quirks", and |
452 | * was never needed for most non-PCI systems ... remove the code? | 452 | * was never needed for most non-PCI systems ... remove the code? |
@@ -502,7 +502,6 @@ static int ohci_init (struct ohci_hcd *ohci) | |||
502 | if ((ret = ohci_mem_init (ohci)) < 0) | 502 | if ((ret = ohci_mem_init (ohci)) < 0) |
503 | ohci_stop (hcd); | 503 | ohci_stop (hcd); |
504 | else { | 504 | else { |
505 | register_reboot_notifier (&ohci->reboot_notifier); | ||
506 | create_debug_files (ohci); | 505 | create_debug_files (ohci); |
507 | } | 506 | } |
508 | 507 | ||
@@ -637,10 +636,14 @@ retry: | |||
637 | return -EOVERFLOW; | 636 | return -EOVERFLOW; |
638 | } | 637 | } |
639 | 638 | ||
640 | /* start controller operations */ | 639 | /* use rhsc irqs after khubd is fully initialized */ |
640 | hcd->poll_rh = 1; | ||
641 | hcd->uses_new_polling = 1; | ||
642 | |||
643 | /* start controller operations */ | ||
641 | ohci->hc_control &= OHCI_CTRL_RWC; | 644 | ohci->hc_control &= OHCI_CTRL_RWC; |
642 | ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; | 645 | ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; |
643 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 646 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
644 | hcd->state = HC_STATE_RUNNING; | 647 | hcd->state = HC_STATE_RUNNING; |
645 | 648 | ||
646 | /* wake on ConnectStatusChange, matching external hubs */ | 649 | /* wake on ConnectStatusChange, matching external hubs */ |
@@ -648,7 +651,7 @@ retry: | |||
648 | 651 | ||
649 | /* Choose the interrupts we care about now, others later on demand */ | 652 | /* Choose the interrupts we care about now, others later on demand */ |
650 | mask = OHCI_INTR_INIT; | 653 | mask = OHCI_INTR_INIT; |
651 | ohci_writel (ohci, mask, &ohci->regs->intrstatus); | 654 | ohci_writel (ohci, ~0, &ohci->regs->intrstatus); |
652 | ohci_writel (ohci, mask, &ohci->regs->intrenable); | 655 | ohci_writel (ohci, mask, &ohci->regs->intrenable); |
653 | 656 | ||
654 | /* handle root hub init quirks ... */ | 657 | /* handle root hub init quirks ... */ |
@@ -672,6 +675,7 @@ retry: | |||
672 | // flush those writes | 675 | // flush those writes |
673 | (void) ohci_readl (ohci, &ohci->regs->control); | 676 | (void) ohci_readl (ohci, &ohci->regs->control); |
674 | 677 | ||
678 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; | ||
675 | spin_unlock_irq (&ohci->lock); | 679 | spin_unlock_irq (&ohci->lock); |
676 | 680 | ||
677 | // POTPGT delay is bits 24-31, in 2 ms units. | 681 | // POTPGT delay is bits 24-31, in 2 ms units. |
@@ -709,7 +713,23 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) | |||
709 | /* interrupt for some other device? */ | 713 | /* interrupt for some other device? */ |
710 | } else if ((ints &= ohci_readl (ohci, ®s->intrenable)) == 0) { | 714 | } else if ((ints &= ohci_readl (ohci, ®s->intrenable)) == 0) { |
711 | return IRQ_NOTMINE; | 715 | return IRQ_NOTMINE; |
712 | } | 716 | } |
717 | |||
718 | /* NOTE: vendors didn't always make the same implementation | ||
719 | * choices for RHSC. Sometimes it triggers on an edge (like | ||
720 | * setting and maybe clearing a port status change bit); and | ||
721 | * it's level-triggered on other silicon, active until khubd | ||
722 | * clears all active port status change bits. Poll by timer | ||
723 | * til it's fully debounced and the difference won't matter. | ||
724 | */ | ||
725 | if (ints & OHCI_INTR_RHSC) { | ||
726 | ohci_vdbg (ohci, "rhsc\n"); | ||
727 | ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrdisable); | ||
728 | hcd->poll_rh = 1; | ||
729 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; | ||
730 | ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrstatus); | ||
731 | usb_hcd_poll_rh_status(hcd); | ||
732 | } | ||
713 | 733 | ||
714 | if (ints & OHCI_INTR_UE) { | 734 | if (ints & OHCI_INTR_UE) { |
715 | disable (ohci); | 735 | disable (ohci); |
@@ -775,9 +795,10 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
775 | 795 | ||
776 | ohci_usb_reset (ohci); | 796 | ohci_usb_reset (ohci); |
777 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | 797 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); |
778 | 798 | free_irq(hcd->irq, hcd); | |
799 | hcd->irq = -1; | ||
800 | |||
779 | remove_debug_files (ohci); | 801 | remove_debug_files (ohci); |
780 | unregister_reboot_notifier (&ohci->reboot_notifier); | ||
781 | ohci_mem_cleanup (ohci); | 802 | ohci_mem_cleanup (ohci); |
782 | if (ohci->hcca) { | 803 | if (ohci->hcca) { |
783 | dma_free_coherent (hcd->self.controller, | 804 | dma_free_coherent (hcd->self.controller, |
@@ -917,6 +938,10 @@ MODULE_LICENSE ("GPL"); | |||
917 | #include "ohci-at91.c" | 938 | #include "ohci-at91.c" |
918 | #endif | 939 | #endif |
919 | 940 | ||
941 | #ifdef CONFIG_ARCH_PNX4008 | ||
942 | #include "ohci-pnx4008.c" | ||
943 | #endif | ||
944 | |||
920 | #if !(defined(CONFIG_PCI) \ | 945 | #if !(defined(CONFIG_PCI) \ |
921 | || defined(CONFIG_SA1111) \ | 946 | || defined(CONFIG_SA1111) \ |
922 | || defined(CONFIG_ARCH_S3C2410) \ | 947 | || defined(CONFIG_ARCH_S3C2410) \ |
@@ -928,6 +953,7 @@ MODULE_LICENSE ("GPL"); | |||
928 | || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ | 953 | || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ |
929 | || defined (CONFIG_ARCH_AT91RM9200) \ | 954 | || defined (CONFIG_ARCH_AT91RM9200) \ |
930 | || defined (CONFIG_ARCH_AT91SAM9261) \ | 955 | || defined (CONFIG_ARCH_AT91SAM9261) \ |
956 | || defined (CONFIG_ARCH_PNX4008) \ | ||
931 | ) | 957 | ) |
932 | #error "missing bus glue for ohci-hcd" | 958 | #error "missing bus glue for ohci-hcd" |
933 | #endif | 959 | #endif |