# 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 <linux/config.h>
 #include <linux/module.h>
+#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/completion.h>
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 <linux/interrupt.h>  /* for in_interrupt () */
 
 #ifdef CONFIG_USB_DEBUG
-	#define DEBUG
+#	define DEBUG
 #else
-	#undef DEBUG
+#	undef DEBUG
 #endif
 
 #include <linux/usb.h>
@@ -92,15 +92,6 @@
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
 
-#ifdef CONFIG_PMAC_PBOOK
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
-#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 <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * 
+ * [ 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 <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/pci-bridge.h>
+#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 <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Hewlett-Packard Company
+ * 
+ * SA1111 Bus Glue
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ * Based on fragments of previous driver by Rusell King et al.
+ *
+ * This file is licenced under the GPL.
+ */
+ 
+#include <asm/hardware.h>
+#include <asm/arch/assabet.h>
+#include <asm/arch/badge4.h>
+#include <asm/hardware/sa1111.h>
+
+#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 <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/pci.h>
 #include <linux/errno.h>
 
 #include <asm/hardware.h>
@@ -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 <linux/timer.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>  /* for in_interrupt() */
-#undef DEBUG
+
+#ifdef CONFIG_USB_DEBUG
+#	define DEBUG
+#else
+#	undef DEBUG
+#endif
 #include <linux/usb.h>
 
 #include <asm/io.h>
@@ -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);