# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.475 -> 1.476 # drivers/usb/host/usb-ohci-sa1111.c 1.1 -> 1.2 # drivers/usb/host/ohci-hcd.c 1.12 -> 1.13 # drivers/usb/host/usb-ohci.c 1.35 -> 1.36 # drivers/usb/core/hcd.h 1.10 -> 1.11 # drivers/usb/core/hcd.c 1.24 -> 1.25 # drivers/usb/host/usb-ohci-pci.c 1.1 -> 1.2 # drivers/usb/host/ohci-mem.c 1.5 -> 1.6 # drivers/usb/host/ohci-q.c 1.8 -> 1.9 # drivers/usb/host/ohci.h 1.5 -> 1.6 # (new) -> 1.1 drivers/usb/host/ohci-sa1111.c # (new) -> 1.1 drivers/usb/host/ohci-pci.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/06/08 ch@murgatroid.com 1.476 # [PATCH] USB SA-1111 patch against usb-2.5 bitkeeper # # This adds SA-1111 support for ohci-hcd and fixes usb-ohci too. # -------------------------------------------- # diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c --- a/drivers/usb/core/hcd.c Sat Jun 8 15:45:52 2002 +++ b/drivers/usb/core/hcd.c Sat Jun 8 15:45:52 2002 @@ -24,6 +24,7 @@ #include #include +#include #include #include #include diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h --- a/drivers/usb/core/hcd.h Sat Jun 8 15:45:52 2002 +++ b/drivers/usb/core/hcd.h Sat Jun 8 15:45:52 2002 @@ -50,9 +50,9 @@ int irq; /* irq allocated */ void *regs; /* device memory/io */ -#ifdef CONFIG_PCI /* a few non-PCI controllers exist, mostly for OHCI */ struct pci_dev *pdev; /* pci is typical */ +#ifdef CONFIG_PCI int region; /* pci region for regs */ u32 pci_state [16]; /* for PM state save */ atomic_t resume_count; /* multiple resumes issue */ diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c Sat Jun 8 15:45:52 2002 +++ b/drivers/usb/host/ohci-hcd.c Sat Jun 8 15:45:52 2002 @@ -78,9 +78,9 @@ #include /* for in_interrupt () */ #ifdef CONFIG_USB_DEBUG - #define DEBUG +# define DEBUG #else - #undef DEBUG +# undef DEBUG #endif #include @@ -92,15 +92,6 @@ #include #include -#ifdef CONFIG_PMAC_PBOOK -#include -#include -#include -#ifndef CONFIG_PM -# define CONFIG_PM -#endif -#endif - /* * TO DO: * @@ -226,7 +217,7 @@ case PIPE_ISOCHRONOUS: if (urb->transfer_flags & USB_ISO_ASAP) { urb->start_frame = ( (ed->state == ED_OPER) - ? (ed->last_iso + 1) + ? (ed->intriso.last_iso + 1) : (le16_to_cpu (ohci->hcca->frame_no) + 10)) & 0xffff; } @@ -411,7 +402,7 @@ __u32 mask; unsigned int fminterval; struct usb_device *udev; - + spin_lock_init (&ohci->lock); ohci->disabled = 1; ohci->sleeping = 0; @@ -462,7 +453,7 @@ usb_connect (udev); udev->speed = USB_SPEED_FULL; - if (usb_register_root_hub (udev, &ohci->hcd.pdev->dev) != 0) { + if (usb_register_root_hub (udev, ohci->parent_dev) != 0) { usb_free_dev (udev); ohci->disabled = 1; // FIXME cleanup @@ -545,167 +536,19 @@ ohci_mem_cleanup (ohci); -#ifdef CONFIG_PCI pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca, ohci->hcca, ohci->hcca_dma); -#endif } /*-------------------------------------------------------------------------*/ -static int __devinit -ohci_start (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - -#ifdef CONFIG_PCI - if (hcd->pdev) { - ohci->hcca = pci_alloc_consistent (hcd->pdev, - sizeof *ohci->hcca, &ohci->hcca_dma); - if (!ohci->hcca) - return -ENOMEM; - - /* AMD 756, for most chips (early revs), corrupts register - * values on read ... so enable the vendor workaround. - */ - if (hcd->pdev->vendor == 0x1022 - && hcd->pdev->device == 0x740c) { - ohci->flags = OHCI_QUIRK_AMD756; - info ("%s: AMD756 erratum 4 workaround", - hcd->self.bus_name); - } - - /* Apple's OHCI driver has a lot of bizarre workarounds - * for this chip. Evidently control and bulk lists - * can get confused. (B&W G3 models, and ...) - */ - else if (hcd->pdev->vendor == 0x1045 - && hcd->pdev->device == 0xc861) { - info ("%s: WARNING: OPTi workarounds unavailable", - hcd->self.bus_name); - } - } -#else -# error "where's hcca coming from?" -#endif /* CONFIG_PCI */ - - memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); - if ((ret = ohci_mem_init (ohci)) < 0) { - ohci_stop (hcd); - return ret; - } - ohci->regs = hcd->regs; - - if (hc_reset (ohci) < 0) { - ohci_stop (hcd); - return -ENODEV; - } - - if (hc_start (ohci) < 0) { - err ("can't start %s", ohci->hcd.self.bus_name); - ohci_stop (hcd); - return -EBUSY; - } - -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PM - -static int ohci_suspend (struct usb_hcd *hcd, u32 state) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - unsigned long flags; - u16 cmd; - - if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { - dbg ("can't suspend %s (state is %s)", hcd->self.bus_name, - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); - return -EIO; - } - - /* act as if usb suspend can always be used */ - dbg ("%s: suspend to %d", hcd->self.bus_name, state); - ohci->sleeping = 1; - - /* First stop processing */ - spin_lock_irqsave (&ohci->lock, flags); - ohci->hc_control &= - ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); - writel (ohci->hc_control, &ohci->regs->control); - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - (void) readl (&ohci->regs->intrstatus); - spin_unlock_irqrestore (&ohci->lock, flags); - - /* Wait a frame or two */ - mdelay (1); - if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) - mdelay (1); - - #ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - disable_irq (hcd->pdev->irq); - /* else, 2.4 assumes shared irqs -- don't disable */ - #endif - - /* Enable remote wakeup */ - writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD, - &ohci->regs->intrenable); - - /* Suspend chip and let things settle down a bit */ - ohci->hc_control = OHCI_USB_SUSPEND; - writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (500); /* No schedule here ! */ - - switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { - case OHCI_USB_RESET: - dbg ("%s suspend->reset ?", hcd->self.bus_name); - break; - case OHCI_USB_RESUME: - dbg ("%s suspend->resume ?", hcd->self.bus_name); - break; - case OHCI_USB_OPER: - dbg ("%s suspend->operational ?", hcd->self.bus_name); - break; - case OHCI_USB_SUSPEND: - dbg ("%s suspended", hcd->self.bus_name); - break; - } - - /* In some rare situations, Apple's OHCI have happily trashed - * memory during sleep. We disable its bus master bit during - * suspend - */ - pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd); - cmd &= ~PCI_COMMAND_MASTER; - pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd); -#ifdef CONFIG_PMAC_PBOOK - { - struct device_node *of_node; - - /* Disable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (hcd->pdev); - if (of_node) - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); - } -#endif - return 0; -} - - // FIXME: this restart logic should be generic, // and handle full hcd state cleanup /* controller died; cleanup debris, then restart */ /* must not be called from interrupt context */ +#ifdef CONFIG_PM static int hc_restart (struct ohci_hcd *ohci) { int temp; @@ -735,227 +578,26 @@ dbg ("restart %s completed", ohci->hcd.self.bus_name); return 0; } - -static int ohci_resume (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int temp; - int retval = 0; - unsigned long flags; - -#ifdef CONFIG_PMAC_PBOOK - { - struct device_node *of_node; - - /* Re-enable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (hcd->pdev); - if (of_node) - pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); - } #endif - /* did we suspend, or were we powered off? */ - ohci->hc_control = readl (&ohci->regs->control); - temp = ohci->hc_control & OHCI_CTRL_HCFS; - -#ifdef DEBUG - /* the registers may look crazy here */ - ohci_dump_status (ohci); -#endif - - /* Re-enable bus mastering */ - pci_set_master (ohci->hcd.pdev); - - switch (temp) { - - case OHCI_USB_RESET: // lost power - info ("USB restart: %s", hcd->self.bus_name); - retval = hc_restart (ohci); - break; - - case OHCI_USB_SUSPEND: // host wakeup - case OHCI_USB_RESUME: // remote wakeup - info ("USB continue: %s from %s wakeup", hcd->self.bus_name, - (temp == OHCI_USB_SUSPEND) - ? "host" : "remote"); - ohci->hc_control = OHCI_USB_RESUME; - writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (20); /* no schedule here ! */ - /* Some controllers (lucent) need a longer delay here */ - mdelay (15); - - temp = readl (&ohci->regs->control); - temp = ohci->hc_control & OHCI_CTRL_HCFS; - if (temp != OHCI_USB_RESUME) { - err ("controller %s won't resume", hcd->self.bus_name); - ohci->disabled = 1; - retval = -EIO; - break; - } - - /* Some chips likes being resumed first */ - writel (OHCI_USB_OPER, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (3); - - /* Then re-enable operations */ - spin_lock_irqsave (&ohci->lock, flags); - ohci->disabled = 0; - ohci->sleeping = 0; - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - if (!ohci->ed_rm_list) { - if (ohci->ed_controltail) - ohci->hc_control |= OHCI_CTRL_CLE; - if (ohci->ed_bulktail) - ohci->hc_control |= OHCI_CTRL_BLE; - } - hcd->state = USB_STATE_READY; - writel (ohci->hc_control, &ohci->regs->control); - - /* trigger a start-frame interrupt (why?) */ - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - - /* Check for a pending done list */ - writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); - (void) readl (&ohci->regs->intrdisable); - spin_unlock_irqrestore (&ohci->lock, flags); - - #ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - enable_irq (hcd->pdev->irq); - #endif - if (ohci->hcca->done_head) - dl_done_list (ohci, dl_reverse_done_list (ohci)); - writel (OHCI_INTR_WDH, &ohci->regs->intrenable); - - /* assume there are TDs on the bulk and control lists */ - writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus); - -// ohci_dump_status (ohci); -dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled); - break; - - default: - warn ("odd PCI resume for %s", hcd->self.bus_name); - } - return retval; -} - -#endif /* CONFIG_PM */ - /*-------------------------------------------------------------------------*/ static const char hcd_name [] = "ohci-hcd"; -static const struct hc_driver ohci_driver = { - description: hcd_name, - - /* - * generic hardware linkage - */ - irq: ohci_irq, - flags: HCD_MEMORY | HCD_USB11, - - /* - * basic lifecycle operations - */ - start: ohci_start, -#ifdef CONFIG_PM - suspend: ohci_suspend, - resume: ohci_resume, -#endif - stop: ohci_stop, - - /* - * memory lifecycle (except per-request) - */ - hcd_alloc: ohci_hcd_alloc, - hcd_free: ohci_hcd_free, - - /* - * managing i/o requests and associated device resources - */ - urb_enqueue: ohci_urb_enqueue, - urb_dequeue: ohci_urb_dequeue, - free_config: ohci_free_config, - - /* - * scheduling support - */ - get_frame_number: ohci_get_frame, - - /* - * root hub support - */ - hub_status_data: ohci_hub_status_data, - hub_control: ohci_hub_control, -}; - #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_DESCRIPTION (DRIVER_INFO); MODULE_LICENSE ("GPL"); -/*-------------------------------------------------------------------------*/ - #ifdef CONFIG_PCI - -/* There do exist non-PCI implementations of OHCI ... - * Examples include the SA-1111 (ARM) and some MIPS - * and related hardware. - */ - -static const struct pci_device_id __devinitdata pci_ids [] = { { - - /* handle any USB OHCI controller */ - class: (PCI_CLASS_SERIAL_USB << 8) | 0x10, - class_mask: ~0, - driver_data: (unsigned long) &ohci_driver, - - /* no matter who makes it */ - vendor: PCI_ANY_ID, - device: PCI_ANY_ID, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - - }, { /* end: all zeroes */ } -}; -MODULE_DEVICE_TABLE (pci, pci_ids); - -/* pci driver glue; this is a "new style" PCI driver module */ -static struct pci_driver ohci_pci_driver = { - name: (char *) hcd_name, - id_table: pci_ids, - - probe: usb_hcd_pci_probe, - remove: usb_hcd_pci_remove, - -#ifdef CONFIG_PM - suspend: usb_hcd_pci_suspend, - resume: usb_hcd_pci_resume, +#include "ohci-pci.c" #endif -}; - - -static int __init ohci_hcd_init (void) -{ - dbg (DRIVER_INFO); - dbg ("block sizes: ed %d td %d", - sizeof (struct ed), sizeof (struct td)); - return pci_module_init (&ohci_pci_driver); -} -module_init (ohci_hcd_init); -/*-------------------------------------------------------------------------*/ - -static void __exit ohci_hcd_cleanup (void) -{ - pci_unregister_driver (&ohci_pci_driver); -} -module_exit (ohci_hcd_cleanup); - -#endif /* CONFIG_PCI */ +#ifdef CONFIG_SA1111 +#include "ohci-sa1111.c" +#endif +#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111)) +#error "missing bus glue for ohci-hcd" +#endif diff -Nru a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c --- a/drivers/usb/host/ohci-mem.c Sat Jun 8 15:45:52 2002 +++ b/drivers/usb/host/ohci-mem.c Sat Jun 8 15:45:52 2002 @@ -42,12 +42,6 @@ /*-------------------------------------------------------------------------*/ -#ifndef CONFIG_PCI -# error "usb-ohci currently requires PCI-based controllers" - /* to support non-PCI OHCIs, you need custom bus/mem/... glue */ -#endif - - /* Recover a TD/ED using its collision chain */ static inline void * dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma) diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/host/ohci-pci.c Sat Jun 8 15:45:52 2002 @@ -0,0 +1,380 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * [ Initialisation is based on Linus' ] + * [ uhci code and gregs ohci fragments ] + * [ (C) Copyright 1999 Linus Torvalds ] + * [ (C) Copyright 1999 Gregory P. Smith] + * + * PCI Bus Glue + * + * This file is licenced under the GPL. + */ + +#ifdef CONFIG_PMAC_PBOOK +#include +#include +#include +#ifndef CONFIG_PM +# define CONFIG_PM +#endif +#endif + +#ifndef CONFIG_PCI +#error "This file is PCI bus glue. CONFIG_PCI must be defined." +#endif + +/*-------------------------------------------------------------------------*/ + +static int __devinit +ohci_pci_start (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; + + if (hcd->pdev) { + ohci->hcca = pci_alloc_consistent (hcd->pdev, + sizeof *ohci->hcca, &ohci->hcca_dma); + if (!ohci->hcca) + return -ENOMEM; + + /* AMD 756, for most chips (early revs), corrupts register + * values on read ... so enable the vendor workaround. + */ + if (hcd->pdev->vendor == 0x1022 + && hcd->pdev->device == 0x740c) { + ohci->flags = OHCI_QUIRK_AMD756; + info ("%s: AMD756 erratum 4 workaround", + hcd->self.bus_name); + } + + /* Apple's OHCI driver has a lot of bizarre workarounds + * for this chip. Evidently control and bulk lists + * can get confused. (B&W G3 models, and ...) + */ + else if (hcd->pdev->vendor == 0x1045 + && hcd->pdev->device == 0xc861) { + info ("%s: WARNING: OPTi workarounds unavailable", + hcd->self.bus_name); + } + } + + memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); + if ((ret = ohci_mem_init (ohci)) < 0) { + ohci_stop (hcd); + return ret; + } + ohci->regs = hcd->regs; + + ohci->parent_dev = &ohci->hcd.pdev->dev; + + if (hc_reset (ohci) < 0) { + ohci_stop (hcd); + return -ENODEV; + } + + if (hc_start (ohci) < 0) { + err ("can't start %s", ohci->hcd.self.bus_name); + ohci_stop (hcd); + return -EBUSY; + } + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + return 0; +} + +#ifdef CONFIG_PM + +static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + unsigned long flags; + u16 cmd; + + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { + dbg ("can't suspend %s (state is %s)", hcd->self.bus_name, + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); + return -EIO; + } + + /* act as if usb suspend can always be used */ + dbg ("%s: suspend to %d", hcd->self.bus_name, state); + ohci->sleeping = 1; + + /* First stop processing */ + spin_lock_irqsave (&ohci->lock, flags); + ohci->hc_control &= + ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); + writel (ohci->hc_control, &ohci->regs->control); + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + (void) readl (&ohci->regs->intrstatus); + spin_unlock_irqrestore (&ohci->lock, flags); + + /* Wait a frame or two */ + mdelay (1); + if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) + mdelay (1); + +#ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + disable_irq (hcd->pdev->irq); + /* else, 2.4 assumes shared irqs -- don't disable */ +#endif + + /* Enable remote wakeup */ + writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD, + &ohci->regs->intrenable); + + /* Suspend chip and let things settle down a bit */ + ohci->hc_control = OHCI_USB_SUSPEND; + writel (ohci->hc_control, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (500); /* No schedule here ! */ + + switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { + case OHCI_USB_RESET: + dbg ("%s suspend->reset ?", hcd->self.bus_name); + break; + case OHCI_USB_RESUME: + dbg ("%s suspend->resume ?", hcd->self.bus_name); + break; + case OHCI_USB_OPER: + dbg ("%s suspend->operational ?", hcd->self.bus_name); + break; + case OHCI_USB_SUSPEND: + dbg ("%s suspended", hcd->self.bus_name); + break; + } + + /* In some rare situations, Apple's OHCI have happily trashed + * memory during sleep. We disable its bus master bit during + * suspend + */ + pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd); + cmd &= ~PCI_COMMAND_MASTER; + pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd); +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Disable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (hcd->pdev); + if (of_node) + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); + } +#endif + return 0; +} + + +static int ohci_pci_resume (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int temp; + int retval = 0; + unsigned long flags; + +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Re-enable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (hcd->pdev); + if (of_node) + pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); + } +#endif + /* did we suspend, or were we powered off? */ + ohci->hc_control = readl (&ohci->regs->control); + temp = ohci->hc_control & OHCI_CTRL_HCFS; + +#ifdef DEBUG + /* the registers may look crazy here */ + ohci_dump_status (ohci); +#endif + + /* Re-enable bus mastering */ + pci_set_master (ohci->hcd.pdev); + + switch (temp) { + + case OHCI_USB_RESET: // lost power + info ("USB restart: %s", hcd->self.bus_name); + retval = hc_restart (ohci); + break; + + case OHCI_USB_SUSPEND: // host wakeup + case OHCI_USB_RESUME: // remote wakeup + info ("USB continue: %s from %s wakeup", hcd->self.bus_name, + (temp == OHCI_USB_SUSPEND) + ? "host" : "remote"); + ohci->hc_control = OHCI_USB_RESUME; + writel (ohci->hc_control, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (20); /* no schedule here ! */ + /* Some controllers (lucent) need a longer delay here */ + mdelay (15); + + temp = readl (&ohci->regs->control); + temp = ohci->hc_control & OHCI_CTRL_HCFS; + if (temp != OHCI_USB_RESUME) { + err ("controller %s won't resume", hcd->self.bus_name); + ohci->disabled = 1; + retval = -EIO; + break; + } + + /* Some chips likes being resumed first */ + writel (OHCI_USB_OPER, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (3); + + /* Then re-enable operations */ + spin_lock_irqsave (&ohci->lock, flags); + ohci->disabled = 0; + ohci->sleeping = 0; + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + if (!ohci->ed_rm_list) { + if (ohci->ed_controltail) + ohci->hc_control |= OHCI_CTRL_CLE; + if (ohci->ed_bulktail) + ohci->hc_control |= OHCI_CTRL_BLE; + } + hcd->state = USB_STATE_READY; + writel (ohci->hc_control, &ohci->regs->control); + + /* trigger a start-frame interrupt (why?) */ + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + + /* Check for a pending done list */ + writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); + (void) readl (&ohci->regs->intrdisable); + spin_unlock_irqrestore (&ohci->lock, flags); + +#ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + enable_irq (hcd->pdev->irq); +#endif + if (ohci->hcca->done_head) + dl_done_list (ohci, dl_reverse_done_list (ohci)); + writel (OHCI_INTR_WDH, &ohci->regs->intrenable); + + /* assume there are TDs on the bulk and control lists */ + writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus); + +// ohci_dump_status (ohci); +dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled); + break; + + default: + warn ("odd PCI resume for %s", hcd->self.bus_name); + } + return retval; +} + +#endif /* CONFIG_PM */ + + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ohci_pci_hc_driver = { + description: hcd_name, + + /* + * generic hardware linkage + */ + irq: ohci_irq, + flags: HCD_MEMORY | HCD_USB11, + + /* + * basic lifecycle operations + */ + start: ohci_pci_start, +#ifdef CONFIG_PM + suspend: ohci_pci_suspend, + resume: ohci_pci_resume, +#endif + stop: ohci_stop, + + /* + * memory lifecycle (except per-request) + */ + hcd_alloc: ohci_hcd_alloc, + hcd_free: ohci_hcd_free, + + /* + * managing i/o requests and associated device resources + */ + urb_enqueue: ohci_urb_enqueue, + urb_dequeue: ohci_urb_dequeue, + free_config: ohci_free_config, + + /* + * scheduling support + */ + get_frame_number: ohci_get_frame, + + /* + * root hub support + */ + hub_status_data: ohci_hub_status_data, + hub_control: ohci_hub_control, +}; + +/*-------------------------------------------------------------------------*/ + + +static const struct pci_device_id __devinitdata pci_ids [] = { { + + /* handle any USB OHCI controller */ + class: (PCI_CLASS_SERIAL_USB << 8) | 0x10, + class_mask: ~0, + driver_data: (unsigned long) &ohci_pci_hc_driver, + + /* no matter who makes it */ + vendor: PCI_ANY_ID, + device: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + }, { /* end: all zeroes */ } +}; +MODULE_DEVICE_TABLE (pci, pci_ids); + +/* pci driver glue; this is a "new style" PCI driver module */ +static struct pci_driver ohci_pci_driver = { + name: (char *) hcd_name, + id_table: pci_ids, + + probe: usb_hcd_pci_probe, + remove: usb_hcd_pci_remove, + +#ifdef CONFIG_PM + suspend: usb_hcd_pci_suspend, + resume: usb_hcd_pci_resume, +#endif +}; + + +static int __init ohci_hcd_pci_init (void) +{ + dbg (DRIVER_INFO " (PCI)"); + dbg ("block sizes: ed %d td %d", + sizeof (struct ed), sizeof (struct td)); + return pci_module_init (&ohci_pci_driver); +} +module_init (ohci_hcd_pci_init); + +/*-------------------------------------------------------------------------*/ + +static void __exit ohci_hcd_pci_cleanup (void) +{ + pci_unregister_driver (&ohci_pci_driver); +} +module_exit (ohci_hcd_pci_cleanup); diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c Sat Jun 8 15:45:52 2002 +++ b/drivers/usb/host/ohci-q.c Sat Jun 8 15:45:52 2002 @@ -15,7 +15,6 @@ if (last >= 0) { int i; struct td *td = urb_priv->td [0]; -#ifdef CONFIG_PCI int len = td->urb->transfer_buffer_length; int dir = usb_pipeout (td->urb->pipe) ? PCI_DMA_TODEVICE @@ -36,10 +35,6 @@ if (len && td->data_dma) pci_unmap_single (hc->hcd.pdev, td->data_dma, len, dir); -#else -# warning "assuming no buffer unmapping is needed" -#endif - for (i = 0; i <= last; i++) { td = urb_priv->td [i]; if (td) @@ -90,7 +85,6 @@ urb_priv_t *urb_priv = urb->hcpriv; unsigned long flags; -#ifdef CONFIG_PCI // FIXME rewrite this resubmit path. use pci_dma_sync_single() // and requeue more cheaply, and only if needed. // Better yet ... abolish the notion of automagic resubmission. @@ -100,7 +94,6 @@ usb_pipeout (urb->pipe) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); -#endif /* FIXME: MP race. If another CPU partially unlinks * this URB (urb->status was updated, hasn't yet told * us to dequeue) before we call complete() here, an @@ -236,11 +229,11 @@ break; case PIPE_INTERRUPT: - load = ed->int_load; - interval = ep_2_n_interval (ed->int_period); + load = ed->intriso.intr_info.int_load; + interval = ep_2_n_interval (ed->intriso.intr_info.int_period); ed->interval = interval; int_branch = ep_int_balance (ohci, interval, load); - ed->int_branch = int_branch; + ed->intriso.intr_info.int_branch = int_branch; for (i = 0; i < ep_rev (6, interval); i += inter) { inter = 1; @@ -355,9 +348,9 @@ break; case PIPE_INTERRUPT: - periodic_unlink (ohci, ed, ed->int_branch, ed->interval); - for (i = ed->int_branch; i < NUM_INTS; i += ed->interval) - ohci->ohci_int_load [i] -= ed->int_load; + periodic_unlink (ohci, ed, ed->intriso.intr_info.int_branch, ed->interval); + for (i = ed->intriso.intr_info.int_branch; i < NUM_INTS; i += ed->interval) + ohci->ohci_int_load [i] -= ed->intriso.intr_info.int_load; #ifdef OHCI_VERBOSE_DEBUG ohci_dump_periodic (ohci, "UNLINK_INT"); #endif @@ -466,8 +459,8 @@ << 16); if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { - ed->int_period = interval; - ed->int_load = load; + ed->intriso.intr_info.int_period = interval; + ed->intriso.intr_info.int_load = load; } spin_unlock_irqrestore (&ohci->lock, flags); @@ -563,7 +556,7 @@ td->hwINFO = cpu_to_le32 (info); if ((td->ed->type) == PIPE_ISOCHRONOUS) { td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); - td->ed->last_iso = info & 0xffff; + td->ed->intriso.last_iso = info & 0xffff; } else { td->hwCBP = cpu_to_le32 (data); } @@ -610,16 +603,11 @@ urb_priv->td_cnt = 0; if (data_len) { -#ifdef CONFIG_PCI data = pci_map_single (ohci->hcd.pdev, - urb->transfer_buffer, data_len, - usb_pipeout (urb->pipe) - ? PCI_DMA_TODEVICE - : PCI_DMA_FROMDEVICE - ); -#else -# error "what dma addr to use" -#endif + urb->transfer_buffer, data_len, + usb_pipeout (urb->pipe) + ? PCI_DMA_TODEVICE + : PCI_DMA_FROMDEVICE); } else data = 0; @@ -667,14 +655,10 @@ /* control requests don't use toggle state */ info = TD_CC | TD_DP_SETUP | TD_T_DATA0; td_fill (ohci, info, -#ifdef CONFIG_PCI pci_map_single (ohci->hcd.pdev, - urb->setup_packet, 8, - PCI_DMA_TODEVICE), -#else -# error "what dma addr to use" -#endif - 8, urb, cnt++); + urb->setup_packet, 8, + PCI_DMA_TODEVICE), + 8, urb, cnt++); if (data_len > 0) { info = TD_CC | TD_R | TD_T_DATA1; info |= usb_pipeout (urb->pipe) diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/host/ohci-sa1111.c Sat Jun 8 15:45:52 2002 @@ -0,0 +1,358 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * (C) Hewlett-Packard Company + * + * SA1111 Bus Glue + * + * Written by Christopher Hoover + * Based on fragments of previous driver by Rusell King et al. + * + * This file is licenced under the GPL. + */ + +#include +#include +#include +#include + +#ifndef CONFIG_SA1111 +#error "This file is SA-1111 bus glue. CONFIG_SA1111 must be defined." +#endif + +/*-------------------------------------------------------------------------*/ + +static void sa1111_start_hc(void) +{ + unsigned int usb_rst = 0; + + printk(KERN_DEBUG __FILE__ + ": starting SA-1111 OHCI USB Controller\n"); + +#ifdef CONFIG_SA1100_BADGE4 + if (machine_is_badge4()) { + badge4_set_5V(BADGE4_5V_USB, 1); + } +#endif + + if (machine_is_xp860() || + machine_has_neponset() || + machine_is_pfs168() || + machine_is_badge4()) + usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW; + + /* + * Configure the power sense and control lines. Place the USB + * host controller in reset. + */ + USB_RESET = usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET; + + /* + * Now, carefully enable the USB clock, and take + * the USB host controller out of reset. + */ + SKPCR |= SKPCR_UCLKEN; + udelay(11); + USB_RESET = usb_rst; +} + +static void sa1111_stop_hc(void) +{ + printk(KERN_DEBUG __FILE__ + ": stopping SA-1111 OHCI USB Controller\n"); + + /* + * Put the USB host controller into reset. + */ + USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET; + + /* + * Stop the USB clock. + */ + SKPCR &= ~SKPCR_UCLKEN; + +#ifdef CONFIG_SA1100_BADGE4 + if (machine_is_badge4()) { + /* Disable power to the USB bus */ + badge4_set_5V(BADGE4_5V_USB, 0); + } +#endif +} + + +/*-------------------------------------------------------------------------*/ + +#if 0 +static void dump_hci_status(const char *label) +{ + unsigned long status = USB_STATUS; + + dbg ("%s USB_STATUS = { %s%s%s%s%s}", label, + ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""), + ((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""), + ((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "), + ((status & USB_STATUS_NHCIMFCLR) ? "" : "HCIMFCLR "), + ((status & USB_STATUS_USBPWRSENSE) ? "USBPWRSENSE " : "")); +} +#endif + +static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r) +{ + //dump_hci_status("irq"); + +#if 0 + /* may work better this way -- need to investigate further */ + if (USB_STATUS & USB_STATUS_NIRQHCIM) { + //dbg ("not normal HC interrupt; ignoring"); + return; + } +#endif + + usb_hcd_irq(irq, __hcd, r); +} + +/*-------------------------------------------------------------------------*/ + +void usb_hcd_sa1111_remove (struct usb_hcd *); + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + + +/** + * usb_hcd_sa1111_probe - initialize SA-1111-based HCDs + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + * Store this function in the HCD's struct pci_driver as probe(). + */ +int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_out) +{ + int retval; + struct usb_hcd *hcd = 0; + + if (!sa1111) + return -ENODEV; + + if (!request_mem_region(_USB_OHCI_OP_BASE, + _USB_EXTENT, hcd_name)) { + dbg("request_mem_region failed"); + return -EBUSY; + } + + sa1111_start_hc(); + + hcd = driver->hcd_alloc (); + if (hcd == NULL){ + dbg ("hcd_alloc failed"); + retval = -ENOMEM; + goto err1; + } + + hcd->driver = (struct hc_driver *) driver; + hcd->description = driver->description; + hcd->irq = NIRQHCIM; + hcd->regs = (void *) &USB_OHCI_OP_BASE; + hcd->pdev = SA1111_FAKE_PCIDEV; + + set_irq_type(NIRQHCIM, IRQT_RISING); + retval = request_irq (NIRQHCIM, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT, + hcd->description, hcd); + if (retval != 0) { + dbg("request_irq failed"); + retval = -EBUSY; + goto err2; + } + + info ("%s (SA-1111) at 0x%p, irq %d\n", + hcd->description, hcd->regs, hcd->irq); + + usb_bus_init (&hcd->self); + hcd->self.op = &usb_hcd_operations; + hcd->self.hcpriv = (void *) hcd; + hcd->self.bus_name = "SA-1111"; + hcd->product_desc = "SA-1111 OHCI"; + + INIT_LIST_HEAD (&hcd->dev_list); + + usb_register_bus (&hcd->self); + + if ((retval = driver->start (hcd)) < 0) + { + usb_hcd_sa1111_remove(hcd); + return retval; + } + + *hcd_out = hcd; + return 0; + + err2: + if (hcd) driver->hcd_free(hcd); + err1: + sa1111_stop_hc(); + release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); + return retval; +} + + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_hcd_sa1111_remove - shutdown processing for SA-1111-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_sa1111_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * + */ +void usb_hcd_sa1111_remove (struct usb_hcd *hcd) +{ + struct usb_device *hub; + void *base; + + info ("remove: %s, state %x", hcd->self.bus_name, hcd->state); + + if (in_interrupt ()) BUG (); + + hub = hcd->self.root_hub; + hcd->state = USB_STATE_QUIESCING; + + dbg ("%s: roothub graceful disconnect", hcd->self.bus_name); + usb_disconnect (&hub); + + hcd->driver->stop (hcd); + hcd->state = USB_STATE_HALT; + + free_irq (hcd->irq, hcd); + + usb_deregister_bus (&hcd->self); + if (atomic_read (&hcd->self.refcnt) != 1) + err (__FUNCTION__ ": %s, count != 1", hcd->self.bus_name); + + base = hcd->regs; + hcd->driver->hcd_free (hcd); + + sa1111_stop_hc(); + release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); +} + +/*-------------------------------------------------------------------------*/ + +static int __devinit +ohci_sa1111_start (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; + + if (hcd->pdev) { + ohci->hcca = pci_alloc_consistent (hcd->pdev, + sizeof *ohci->hcca, &ohci->hcca_dma); + if (!ohci->hcca) + return -ENOMEM; + } + + memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); + if ((ret = ohci_mem_init (ohci)) < 0) { + ohci_stop (hcd); + return ret; + } + ohci->regs = hcd->regs; + + ohci->parent_dev = &sa1111->dev; + + if (hc_reset (ohci) < 0) { + ohci_stop (hcd); + return -ENODEV; + } + + if (hc_start (ohci) < 0) { + err ("can't start %s", ohci->hcd.self.bus_name); + ohci_stop (hcd); + return -EBUSY; + } + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static const struct hc_driver ohci_sa1111_hc_driver = { + description: hcd_name, + + /* + * generic hardware linkage + */ + irq: ohci_irq, + flags: HCD_USB11, + + /* + * basic lifecycle operations + */ + start: ohci_sa1111_start, +#ifdef CONFIG_PM + /* suspend: ohci_sa1111_suspend, -- tbd */ + /* resume: ohci_sa1111_resume, -- tbd */ +#endif + stop: ohci_stop, + + /* + * memory lifecycle (except per-request) + */ + hcd_alloc: ohci_hcd_alloc, + hcd_free: ohci_hcd_free, + + /* + * managing i/o requests and associated device resources + */ + urb_enqueue: ohci_urb_enqueue, + urb_dequeue: ohci_urb_dequeue, + free_config: ohci_free_config, + + /* + * scheduling support + */ + get_frame_number: ohci_get_frame, + + /* + * root hub support + */ + hub_status_data: ohci_hub_status_data, + hub_control: ohci_hub_control, +}; + +/*-------------------------------------------------------------------------*/ + +/* Only one SA-1111 ever exists. */ +static struct usb_hcd *the_sa1111_hcd; + +static int __init ohci_hcd_sa1111_init (void) +{ + dbg (DRIVER_INFO " (SA-1111)"); + dbg ("block sizes: ed %d td %d", + sizeof (struct ed), sizeof (struct td)); + + the_sa1111_hcd = 0; + return usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &the_sa1111_hcd); +} +module_init (ohci_hcd_sa1111_init); + + +static void __exit ohci_hcd_sa1111_cleanup (void) +{ + if (the_sa1111_hcd) { + usb_hcd_sa1111_remove(the_sa1111_hcd); + the_sa1111_hcd = 0; + } +} +module_exit (ohci_hcd_sa1111_cleanup); diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h --- a/drivers/usb/host/ohci.h Sat Jun 8 15:45:52 2002 +++ b/drivers/usb/host/ohci.h Sat Jun 8 15:45:52 2002 @@ -37,9 +37,9 @@ u8 int_period; u8 int_branch; u8 int_load; - }; + } intr_info; u16 last_iso; /* isochronous */ - }; + } intriso; u8 state; /* ED_{NEW,UNLINK,OPER} */ #define ED_NEW 0x00 /* unused, no dummy td */ @@ -331,6 +331,11 @@ struct ohci_hcd { spinlock_t lock; + /* + * parent device + */ + struct device *parent_dev; + /* * I/O memory used to communicate with the HC (uncached); */ @@ -348,12 +353,10 @@ struct ed *ed_controltail; /* last in ctrl list */ struct ed *ed_isotail; /* last in iso list */ -#ifdef CONFIG_PCI struct pci_pool *td_cache; struct pci_pool *ed_cache; struct hash_list_t td_hash [TD_HASH_SIZE]; struct hash_list_t ed_hash [ED_HASH_SIZE]; -#endif /* * driver state diff -Nru a/drivers/usb/host/usb-ohci-pci.c b/drivers/usb/host/usb-ohci-pci.c --- a/drivers/usb/host/usb-ohci-pci.c Sat Jun 8 15:45:52 2002 +++ b/drivers/usb/host/usb-ohci-pci.c Sat Jun 8 15:45:52 2002 @@ -21,6 +21,12 @@ #endif #endif +int __devinit +hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags, + ohci_t **ohci, const char *name, const char *slot_name); +extern void hc_remove_ohci(ohci_t *ohci); +extern int hc_start (ohci_t * ohci, struct device *parent_dev); +extern int hc_reset (ohci_t * ohci); /*-------------------------------------------------------------------------*/ @@ -103,7 +109,8 @@ ohci->ed_controltail = NULL; ohci->ed_bulktail = NULL; - if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { + if ((temp = hc_reset (ohci)) < 0 || + (temp = hc_start (ohci, &ohci->ohci_dev->dev)) < 0) { err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp); } else dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name); @@ -171,6 +178,7 @@ ohci_pci_remove (struct pci_dev *dev) { ohci_t *ohci = (ohci_t *) pci_get_drvdata(dev); + void *membase = ohci->regs; dbg ("remove %s controller usb-%s%s%s", hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), @@ -181,6 +189,9 @@ hc_remove_ohci(ohci); + /* unmap the IO address space */ + iounmap (membase); + release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0)); } diff -Nru a/drivers/usb/host/usb-ohci-sa1111.c b/drivers/usb/host/usb-ohci-sa1111.c --- a/drivers/usb/host/usb-ohci-sa1111.c Sat Jun 8 15:45:52 2002 +++ b/drivers/usb/host/usb-ohci-sa1111.c Sat Jun 8 15:45:52 2002 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,9 @@ hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags, ohci_t **ohci, const char *name, const char *slot_name); extern void hc_remove_ohci(ohci_t *ohci); +extern int hc_start (ohci_t * ohci, struct device *parent_dev); +extern int hc_reset (ohci_t * ohci); + static ohci_t *sa1111_ohci; @@ -34,6 +38,15 @@ { unsigned int usb_rst = 0; + printk(KERN_DEBUG __FILE__ + ": starting SA-1111 OHCI USB Controller\n"); + +#ifdef CONFIG_SA1100_BADGE4 + if (machine_is_badge4()) + /* power the bus */ + badge4_set_5V(BADGE4_5V_USB, 1); +#endif + if (machine_is_xp860() || machine_has_neponset() || machine_is_pfs168() || @@ -55,6 +68,28 @@ USB_RESET = usb_rst; } +static void __exit sa1111_ohci_unconfigure(void) +{ + printk(KERN_DEBUG __FILE__ + ": stopping SA-1111 OHCI USB Controller\n"); + + /* + * Put the USB host controller into reset. + */ + USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET; + + /* + * Stop the USB clock. + */ + SKPCR &= ~SKPCR_UCLKEN; + +#ifdef CONFIG_SA1100_BADGE4 + if (machine_is_badge4()) + badge4_set_5V(BADGE4_5V_USB, 0); +#endif +} + + static int __init sa1111_ohci_init(void) { int ret; @@ -65,66 +100,54 @@ /* * Request memory resources. */ -// if (!request_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT, "usb-ohci")) -// return -EBUSY; + if (!request_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT, "usb-ohci")) + return -EBUSY; sa1111_ohci_configure(); /* * Initialise the generic OHCI driver. */ - ret = hc_add_ohci((struct pci_dev *)1, NIRQHCIM, + sa1111_ohci = 0; + ret = hc_add_ohci(SA1111_FAKE_PCIDEV, NIRQHCIM, (void *)&USB_OHCI_OP_BASE, 0, &sa1111_ohci, "usb-ohci", "sa1111"); - if (ret == 0) { - if (hc_start (sa1111_ohci, &sa1111->dev) < 0) { - err ("can't start usb-%s", sa1111_ohci->slot_name); - hc_remove_ohci (sa1111_ohci); - return -EBUSY; - } + if (ret || !sa1111_ohci) { + sa1111_ohci = 0; + sa1111_ohci_unconfigure(); + release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); + return -EBUSY; + } -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif -#ifdef CONFIG_SA1100_BADGE4 - if (machine_is_badge4()) { - /* found the controller, so now power the bus */ - badge4_set_5V(BADGE4_5V_USB, 1); - } -#endif + if (hc_start (sa1111_ohci, &sa1111->dev) < 0) { + err ("can't start usb-%s", sa1111_ohci->slot_name); + hc_remove_ohci (sa1111_ohci); + sa1111_ohci = 0; + sa1111_ohci_unconfigure(); + release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); + return -EBUSY; } -// else -// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); - return ret; + return 0; } static void __exit sa1111_ohci_exit(void) { - hc_remove_ohci(sa1111_ohci); + printk(KERN_DEBUG __FUNCTION__ ": cleaning up\n"); - /* - * Put the USB host controller into reset. - */ - USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET; - - /* - * Stop the USB clock. - */ - SKPCR &= ~SKPCR_UCLKEN; + if (sa1111_ohci) { + hc_remove_ohci(sa1111_ohci); + sa1111_ohci = 0; + } - /* - * Release memory resources. - */ -// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); + sa1111_ohci_unconfigure(); + release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); -#ifdef CONFIG_SA1100_BADGE4 - if (machine_is_badge4()) { - badge4_set_5V(BADGE4_5V_USB, 0); - } -#endif + printk(KERN_DEBUG __FUNCTION__ ": exiting\n"); } module_init(sa1111_ohci_init); module_exit(sa1111_ohci_exit); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/usb/host/usb-ohci.c b/drivers/usb/host/usb-ohci.c --- a/drivers/usb/host/usb-ohci.c Sat Jun 8 15:45:52 2002 +++ b/drivers/usb/host/usb-ohci.c Sat Jun 8 15:45:52 2002 @@ -66,7 +66,12 @@ #include #include #include /* for in_interrupt() */ -#undef DEBUG + +#ifdef CONFIG_USB_DEBUG +# define DEBUG +#else +# undef DEBUG +#endif #include #include @@ -2391,7 +2396,11 @@ return NULL; } ohci->bus->hcpriv = (void *) ohci; +#ifdef CONFIG_PCI ohci->bus->bus_name = dev->slot_name; +#else + ohci->bus->bus_name = "ohci-hc"; +#endif return ohci; } @@ -2430,9 +2439,6 @@ ohci_mem_cleanup (ohci); - /* unmap the IO address space */ - iounmap (ohci->regs); - pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca, ohci->hcca, ohci->hcca_dma); kfree (ohci);