# 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.592   -> 1.592.2.1
#	drivers/usb/host/usb-ohci.h	1.13    -> 1.14   
#	drivers/usb/host/Config.in	1.11    -> 1.12   
#	drivers/usb/host/usb-ohci.c	1.34    -> 1.35   
#	drivers/usb/Config.in	1.30    -> 1.31   
#	drivers/usb/Makefile	1.31    -> 1.32   
#	drivers/usb/host/Makefile	1.10    -> 1.11   
#	               (new)	        -> 1.1     drivers/usb/host/usb-ohci-sa1111.c
#	               (new)	        -> 1.1     drivers/usb/host/usb-ohci-pci.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/05/29	greg@kroah.com	1.592.2.1
# USB OHCI driver: Added SA1111 support
#   
# Added the patch from Russell King <rmk@arm.linux.org.uk> that splits
# the usb-ohci driver into two pieces, enabling the sa1111 hardware to
# work with the driver.
#   
# I also added some changes to get the usb-ohci-pci.o module to build
# and run properly.
# --------------------------------------------
#
diff -Nru a/drivers/usb/Config.in b/drivers/usb/Config.in
--- a/drivers/usb/Config.in	Fri May 31 00:41:19 2002
+++ b/drivers/usb/Config.in	Fri May 31 00:41:19 2002
@@ -4,7 +4,13 @@
 mainmenu_option next_comment
 comment 'USB support'
 
-dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI
+# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
+if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" ]; then
+   tristate 'Support for USB' CONFIG_USB
+else
+   define_bool CONFIG_USB n
+fi
+
 if [ "$CONFIG_USB" = "y" -o  "$CONFIG_USB" = "m" ]; then
    source drivers/usb/core/Config.in
 
diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile
--- a/drivers/usb/Makefile	Fri May 31 00:41:19 2002
+++ b/drivers/usb/Makefile	Fri May 31 00:41:19 2002
@@ -6,9 +6,11 @@
 mod-subdirs	:= serial
 
 obj-$(CONFIG_USB)		+= core/
+
 obj-$(CONFIG_USB_EHCI_HCD)	+= host/
 obj-$(CONFIG_USB_OHCI_HCD)	+= host/
 obj-$(CONFIG_USB_OHCI)		+= host/
+obj-$(CONFIG_USB_OHCI_SA1111)	+= host/
 obj-$(CONFIG_USB_SL811HS)	+= host/
 obj-$(CONFIG_USB_UHCI_ALT)	+= host/
 obj-$(CONFIG_USB_UHCI_HCD_ALT)	+= host/
diff -Nru a/drivers/usb/host/Config.in b/drivers/usb/host/Config.in
--- a/drivers/usb/host/Config.in	Fri May 31 00:41:19 2002
+++ b/drivers/usb/host/Config.in	Fri May 31 00:41:19 2002
@@ -20,5 +20,6 @@
 #fi
 #dep_tristate '  OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
 if [ "$CONFIG_ARM" = "y" ]; then
+   dep_tristate '  SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB
    dep_tristate '  SL811HS support' CONFIG_USB_SL811HS $CONFIG_USB
 fi
diff -Nru a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
--- a/drivers/usb/host/Makefile	Fri May 31 00:41:19 2002
+++ b/drivers/usb/host/Makefile	Fri May 31 00:41:19 2002
@@ -3,6 +3,8 @@
 # framework and drivers
 #
 
+export-objs := usb-ohci.o
+
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
 obj-$(CONFIG_USB_UHCI_HCD)	+= usb-uhci-hcd.o
@@ -10,7 +12,8 @@
 
 obj-$(CONFIG_USB_UHCI)		+= usb-uhci.o
 obj-$(CONFIG_USB_UHCI_ALT)	+= uhci.o
-obj-$(CONFIG_USB_OHCI)		+= usb-ohci.o
+obj-$(CONFIG_USB_OHCI)		+= usb-ohci.o usb-ohci-pci.o
+obj-$(CONFIG_USB_OHCI_SA1111)	+= usb-ohci.o usb-ohci-sa1111.o
 obj-$(CONFIG_USB_SL811HS)	+= hc_sl811.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/drivers/usb/host/usb-ohci-pci.c b/drivers/usb/host/usb-ohci-pci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/usb-ohci-pci.c	Fri May 31 00:41:19 2002
@@ -0,0 +1,445 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>  /* for in_interrupt() */
+#undef DEBUG
+#include <linux/usb.h>
+
+#include "../core/hcd.h"
+#include "usb-ohci.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
+
+
+/*-------------------------------------------------------------------------*/
+
+/* Increment the module usage count, start the control thread and
+ * return success. */
+
+static struct pci_driver ohci_pci_driver;
+
+static int __devinit
+hc_found_ohci (struct pci_dev *dev, int irq,
+	void *mem_base, const struct pci_device_id *id)
+{
+	u8 latency, limit;
+	ohci_t * ohci;
+	int ret;
+
+	printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
+
+	/* bad pci latencies can contribute to overruns */ 
+	pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+	if (latency) {
+		pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
+		if (limit && limit < latency) {
+			dbg ("PCI latency reduced to max %d", limit);
+			pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
+			latency = limit;
+		}
+	}
+
+	ret = hc_add_ohci(dev, irq, mem_base, id->driver_data,
+			   &ohci, ohci_pci_driver.name, dev->slot_name);
+
+	if (ret == 0) {
+		ohci->pci_latency = latency;
+
+		if (hc_start (ohci, &ohci->ohci_dev->dev) < 0) {
+			err ("can't start usb-%s", ohci->slot_name);
+			hc_remove_ohci(ohci);
+			return -EBUSY;
+		}
+
+#ifdef	DEBUG
+		ohci_dump (ohci, 1);
+#endif
+	}
+
+	return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_PM
+
+/* controller died; cleanup debris, then restart */
+/* must not be called from interrupt context */
+
+static void hc_restart (ohci_t *ohci)
+{
+	int temp;
+	int i;
+
+	if (ohci->pci_latency)
+		pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
+
+	ohci->disabled = 1;
+	ohci->sleeping = 0;
+	if (ohci->bus->root_hub)
+		usb_disconnect (&ohci->bus->root_hub);
+	
+	/* empty the interrupt branches */
+	for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
+	for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
+	
+	/* no EDs to remove */
+	ohci->ed_rm_list [0] = NULL;
+	ohci->ed_rm_list [1] = NULL;
+
+	/* empty control and bulk lists */	 
+	ohci->ed_isotail     = NULL;
+	ohci->ed_controltail = NULL;
+	ohci->ed_bulktail    = NULL;
+
+	if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 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);
+}
+
+#endif	/* CONFIG_PM */
+
+/*-------------------------------------------------------------------------*/
+
+/* configured so that an OHCI device is always provided */
+/* always called with process context; sleeping is OK */
+
+static int __devinit
+ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+{
+	unsigned long mem_resource, mem_len;
+	void *mem_base;
+	int status;
+
+	if (pci_enable_device(dev) < 0)
+		return -ENODEV;
+
+        if (!dev->irq) {
+        	err("found OHCI device with no IRQ assigned. check BIOS settings!");
+		pci_disable_device (dev);
+   	        return -ENODEV;
+        }
+	
+	/* we read its hardware registers as memory */
+	mem_resource = pci_resource_start(dev, 0);
+	mem_len = pci_resource_len(dev, 0);
+	if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
+		dbg ("controller already in use");
+		pci_disable_device (dev);
+		return -EBUSY;
+	}
+
+	mem_base = ioremap_nocache (mem_resource, mem_len);
+	if (!mem_base) {
+		err("Error mapping OHCI memory");
+		release_mem_region(mem_resource, mem_len);
+		pci_disable_device (dev);
+		return -EFAULT;
+	}
+
+	/* controller writes into our memory */
+	pci_set_master (dev);
+
+	status = hc_found_ohci (dev, dev->irq, mem_base, id);
+	if (status < 0) {
+		iounmap (mem_base);
+		release_mem_region(mem_resource, mem_len);
+		pci_disable_device (dev);
+	}
+	return status;
+} 
+
+/*-------------------------------------------------------------------------*/
+
+/* may be called from interrupt context [interface spec] */
+/* may be called without controller present */
+/* may be called with controller, bus, and devices active */
+
+static void __devexit
+ohci_pci_remove (struct pci_dev *dev)
+{
+	ohci_t		*ohci = (ohci_t *) pci_get_drvdata(dev);
+
+	dbg ("remove %s controller usb-%s%s%s",
+		hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
+		dev->slot_name,
+		ohci->disabled ? " (disabled)" : "",
+		in_interrupt () ? " in interrupt" : ""
+		);
+
+	hc_remove_ohci(ohci);
+
+	release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
+}
+
+
+#ifdef	CONFIG_PM
+
+/*-------------------------------------------------------------------------*/
+
+static int
+ohci_pci_suspend (struct pci_dev *dev, u32 state)
+{
+	ohci_t			*ohci = (ohci_t *) pci_get_drvdata(dev);
+	unsigned long		flags;
+	u16 cmd;
+
+	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
+		dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
+			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
+		return -EIO;
+	}
+
+	/* act as if usb suspend can always be used */
+	info ("USB suspend: usb-%s", dev->slot_name);
+	ohci->sleeping = 1;
+
+	/* First stop processing */
+  	spin_lock_irqsave (&usb_ed_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 (&usb_ed_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 (ohci->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("Bus in reset phase ???");
+			break;
+		case OHCI_USB_RESUME:
+			dbg("Bus in resume phase ???");
+			break;
+		case OHCI_USB_OPER:
+			dbg("Bus in operational phase ???");
+			break;
+		case OHCI_USB_SUSPEND:
+			dbg("Bus suspended");
+			break;
+	}
+	/* In some rare situations, Apple's OHCI have happily trashed
+	 * memory during sleep. We disable it's bus master bit during
+	 * suspend
+	 */
+	pci_read_config_word (dev, PCI_COMMAND, &cmd);
+	cmd &= ~PCI_COMMAND_MASTER;
+	pci_write_config_word (dev, PCI_COMMAND, cmd);
+#ifdef CONFIG_PMAC_PBOOK
+	{
+	   	struct device_node	*of_node;
+
+		/* Disable USB PAD & cell clock */
+		of_node = pci_device_to_OF_node (ohci->ohci_dev);
+		if (of_node && _machine == _MACH_Pmac)
+			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
+	}
+#endif
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+ohci_pci_resume (struct pci_dev *dev)
+{
+	ohci_t		*ohci = (ohci_t *) pci_get_drvdata(dev);
+	int		temp;
+	unsigned long	flags;
+
+	/* guard against multiple resumes */
+	atomic_inc (&ohci->resume_count);
+	if (atomic_read (&ohci->resume_count) != 1) {
+		err ("concurrent PCI resumes for usb-%s", dev->slot_name);
+		atomic_dec (&ohci->resume_count);
+		return 0;
+	}
+
+#ifdef CONFIG_PMAC_PBOOK
+	{
+		struct device_node *of_node;
+
+		/* Re-enable USB PAD & cell clock */
+		of_node = pci_device_to_OF_node (ohci->ohci_dev);
+		if (of_node && _machine == _MACH_Pmac)
+			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->ohci_dev);
+	
+	switch (temp) {
+
+	case OHCI_USB_RESET:	// lost power
+		info ("USB restart: usb-%s", dev->slot_name);
+		hc_restart (ohci);
+		break;
+
+	case OHCI_USB_SUSPEND:	// host wakeup
+	case OHCI_USB_RESUME:	// remote wakeup
+		info ("USB continue: usb-%s from %s wakeup", dev->slot_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 usb-%s won't resume", dev->slot_name);
+			ohci->disabled = 1;
+			return -EIO;
+		}
+
+		/* 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 (&usb_ed_lock, flags);
+		ohci->disabled = 0;
+		ohci->sleeping = 0;
+		ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+		if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
+			if (ohci->ed_controltail)
+				ohci->hc_control |= OHCI_CTRL_CLE;
+			if (ohci->ed_bulktail)
+				ohci->hc_control |= OHCI_CTRL_BLE;
+		}
+		writel (ohci->hc_control, &ohci->regs->control);
+		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 (&usb_ed_lock, flags);
+#ifdef CONFIG_PMAC_PBOOK
+		if (_machine == _MACH_Pmac)
+			enable_irq (ohci->irq);
+#endif
+		if (ohci->hcca->done_head)
+			dl_done_list (ohci, dl_reverse_done_list (ohci));
+		writel (OHCI_INTR_WDH, &ohci->regs->intrenable); 
+		writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+		writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+		break;
+
+	default:
+		warn ("odd PCI resume for usb-%s", dev->slot_name);
+	}
+
+	/* controller is operational, extra resumes are harmless */
+	atomic_dec (&ohci->resume_count);
+
+	return 0;
+}
+
+#endif	/* CONFIG_PM */
+
+
+/*-------------------------------------------------------------------------*/
+
+static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
+
+	/*
+	 * AMD-756 [Viper] USB has a serious erratum when used with
+	 * lowspeed devices like mice.
+	 */
+	vendor:		0x1022,
+	device:		0x740c,
+	subvendor:	PCI_ANY_ID,
+	subdevice:	PCI_ANY_ID,
+
+	driver_data:	OHCI_QUIRK_AMD756,
+
+} , {
+
+	/* handle any USB OHCI controller */
+	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x10),
+	class_mask: 	~0,
+
+	/* 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, ohci_pci_ids);
+
+static struct pci_driver ohci_pci_driver = {
+	name:		"usb-ohci",
+	id_table:	&ohci_pci_ids [0],
+
+	probe:		ohci_pci_probe,
+	remove:		__devexit_p(ohci_pci_remove),
+
+#ifdef	CONFIG_PM
+	suspend:	ohci_pci_suspend,
+	resume:		ohci_pci_resume,
+#endif	/* PM */
+};
+
+ 
+/*-------------------------------------------------------------------------*/
+
+static int __init ohci_hcd_init (void) 
+{
+	return pci_module_init (&ohci_pci_driver);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void __exit ohci_hcd_cleanup (void) 
+{	
+	pci_unregister_driver (&ohci_pci_driver);
+}
+
+module_init (ohci_hcd_init);
+module_exit (ohci_hcd_cleanup);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/host/usb-ohci-sa1111.c b/drivers/usb/host/usb-ohci-sa1111.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/usb-ohci-sa1111.c	Fri May 31 00:41:19 2002
@@ -0,0 +1,130 @@
+/*
+ *  linux/drivers/usb/usb-ohci-sa1111.c
+ *
+ *  The outline of this code was taken from Brad Parkers <brad@heeltoe.com>
+ *  original OHCI driver modifications, and reworked into a cleaner form
+ *  by Russell King <rmk@arm.linux.org.uk>.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/errno.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/arch/assabet.h>
+#include <asm/arch/badge4.h>
+#include <asm/hardware/sa1111.h>
+
+#include "usb-ohci.h"
+
+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);
+
+static ohci_t *sa1111_ohci;
+
+static void __init sa1111_ohci_configure(void)
+{
+	unsigned int usb_rst = 0;
+
+	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 int __init sa1111_ohci_init(void)
+{
+	int ret;
+
+	if (!sa1111)
+		return -ENODEV;
+
+	/*
+	 * Request memory resources.
+	 */
+//	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,
+			  (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;
+		}
+
+#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
+	}
+//	else
+//		release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
+
+	return ret;
+}
+
+static void __exit sa1111_ohci_exit(void)
+{
+	hc_remove_ohci(sa1111_ohci);
+
+	/*
+	 * Put the USB host controller into reset.
+	 */
+	USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
+
+	/*
+	 * Stop the USB clock.
+	 */
+	SKPCR &= ~SKPCR_UCLKEN;
+
+	/*
+	 * Release memory resources.
+	 */
+//	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
+}
+
+module_init(sa1111_ohci_init);
+module_exit(sa1111_ohci_exit);
diff -Nru a/drivers/usb/host/usb-ohci.c b/drivers/usb/host/usb-ohci.c
--- a/drivers/usb/host/usb-ohci.c	Fri May 31 00:41:19 2002
+++ b/drivers/usb/host/usb-ohci.c	Fri May 31 00:41:19 2002
@@ -82,16 +82,6 @@
 #include "usb-ohci.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
-
-
 /*
  * Version Information
  */
@@ -99,14 +89,10 @@
 #define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
 #define DRIVER_DESC "USB OHCI Host Controller Driver"
 
-/* For initializing controller (mask in an HCFS mode too) */
-#define	OHCI_CONTROL_INIT \
-	(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
-
 #define OHCI_UNLINK_TIMEOUT	(HZ / 10)
 
 static LIST_HEAD (ohci_hcd_list);
-static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
 
 
 /*-------------------------------------------------------------------------*/
@@ -443,7 +429,7 @@
 
 static void ohci_dump (ohci_t *controller, int verbose)
 {
-	dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name);
+	dbg ("OHCI controller usb-%s state", controller->slot_name);
 
 	// dumps some of the state we know about
 	ohci_dump_status (controller);
@@ -465,7 +451,7 @@
 static int sohci_return_urb (struct ohci *hc, struct urb * urb)
 {
 	urb_priv_t * urb_priv = urb->hcpriv;
-	struct urb * urbt;
+	struct urb * urbt = NULL;
 	unsigned long flags;
 	int i;
 	
@@ -499,7 +485,7 @@
   			break;
   			
 		case PIPE_ISOCHRONOUS:
-			for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next);
+			// for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next);
 			if (urbt) { /* send the reply and requeue URB */	
 				pci_unmap_single (hc->ohci_dev,
 					urb_priv->td [0]->data_dma,
@@ -865,7 +851,7 @@
   				if (ed->state == ED_OPER) {
 					/* driver on that interface didn't unlink an urb */
 					dbg ("driver usb-%s dev %d ed 0x%x unfreed URB",
-						ohci->ohci_dev->slot_name, usb_dev->devnum, i);
+						ohci->slot_name, usb_dev->devnum, i);
 					ep_unlink (ohci, ed);
 				}
   				ep_rm_ed (usb_dev, ed);
@@ -910,7 +896,7 @@
 			} else {
 				/* likely some interface's driver has a refcount bug */
 				err ("bus %s devnum %d deletion in interrupt",
-					ohci->ohci_dev->slot_name, usb_dev->devnum);
+					ohci->slot_name, usb_dev->devnum);
 				BUG ();
 			}
 		}
@@ -1529,7 +1515,7 @@
 /* replies to the request have to be on a FIFO basis so
  * we reverse the reversed done-list */
  
-static td_t * dl_reverse_done_list (ohci_t * ohci)
+td_t * dl_reverse_done_list (ohci_t * ohci)
 {
 	__u32 td_list_hc;
 	td_t * td_rev = NULL;
@@ -1677,7 +1663,7 @@
 
 /* td done list */
 
-static void dl_done_list (ohci_t * ohci, td_t * td_list)
+void dl_done_list (ohci_t * ohci, td_t * td_list)
 {
   	td_t * td_list_next = NULL;
 	ed_t * ed;
@@ -1822,7 +1808,7 @@
 	num_ports = roothub_a (ohci) & RH_A_NDP; 
 	if (num_ports > MAX_ROOT_PORTS) {
 		err ("bogus NDP=%d for OHCI usb-%s", num_ports,
-			ohci->ohci_dev->slot_name);
+			ohci->slot_name);
 		err ("rereads as NDP=%d",
 			readl (&ohci->regs->roothub.a) & RH_A_NDP);
 		/* retry later; "should not happen" */
@@ -2148,7 +2134,7 @@
 
 /* reset the HC and BUS */
 
-static int hc_reset (ohci_t * ohci)
+int hc_reset (ohci_t * ohci)
 {
 	int timeout = 30;
 	int smm_timeout = 50; /* 0,5 sec */
@@ -2169,7 +2155,7 @@
 	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
 
 	dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;",
-		ohci->ohci_dev->slot_name,
+		ohci->slot_name,
 		readl (&ohci->regs->control));
 
   	/* Reset USB (needed by some controllers) */
@@ -2193,7 +2179,7 @@
  * enable interrupts 
  * connect the virtual root hub */
 
-static int hc_start (ohci_t * ohci)
+int hc_start (ohci_t * ohci, struct device *parent_dev)
 {
   	__u32 mask;
   	unsigned int fminterval;
@@ -2247,7 +2233,7 @@
 	dev = usb_to_ohci (usb_dev);
 	ohci->bus->root_hub = usb_dev;
 	usb_connect (usb_dev);
-	if (usb_register_root_hub (usb_dev, &ohci->ohci_dev->dev) != 0) {
+	if (usb_register_root_hub (usb_dev, parent_dev) != 0) {
 		usb_free_dev (usb_dev); 
 		ohci->disabled = 1;
 		return -ENODEV;
@@ -2308,7 +2294,7 @@
 	if (ints & OHCI_INTR_UE) {
 		ohci->disabled++;
 		err ("OHCI Unrecoverable Error, controller usb-%s disabled",
-			ohci->ohci_dev->slot_name);
+			ohci->slot_name);
 		// e.g. due to PCI Master/Target Abort
 
 #ifdef	DEBUG
@@ -2385,7 +2371,9 @@
 	ohci->regs = mem_base;   
 
 	ohci->ohci_dev = dev;
+#ifdef CONFIG_PCI
 	pci_set_drvdata(dev, ohci);
+#endif
  
 	INIT_LIST_HEAD (&ohci->ohci_hcd_list);
 	list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
@@ -2394,7 +2382,9 @@
 
 	ohci->bus = usb_alloc_bus (&sohci_device_operations);
 	if (!ohci->bus) {
+#ifdef CONFIG_PCI
 		pci_set_drvdata (dev, NULL);
+#endif
 		pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca,
 				ohci->hcca, ohci->hcca_dma);
 		kfree (ohci);
@@ -2413,7 +2403,7 @@
 
 static void hc_release_ohci (ohci_t * ohci)
 {	
-	dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name);
+	dbg ("USB HC release ohci usb-%s", ohci->slot_name);
 
 	/* disconnect all devices */    
 	if (ohci->bus->root_hub)
@@ -2426,7 +2416,9 @@
 		free_irq (ohci->irq, ohci);
 		ohci->irq = -1;
 	}
+#ifdef CONFIG_PCI
 	pci_set_drvdata(ohci->ohci_dev, NULL);
+#endif
 	if (ohci->bus) {
 		if (ohci->bus->busnum)
 			usb_deregister_bus (ohci->bus);
@@ -2448,18 +2440,15 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* Increment the module usage count, start the control thread and
- * return success. */
-
-static struct pci_driver ohci_pci_driver;
- 
-static int __devinit
-hc_found_ohci (struct pci_dev *dev, int irq,
-	void *mem_base, const struct pci_device_id *id)
+/*
+ * Host bus independent add one OHCI host controller.
+ */
+int
+hc_add_ohci(struct pci_dev *dev, int irq, void *mem_base, unsigned long flags,
+	    ohci_t **ohcip, const char *name, const char *slot_name)
 {
-	ohci_t * ohci;
-	u8 latency, limit;
 	char buf[8], *bufp = buf;
+	ohci_t * ohci;
 	int ret;
 
 #ifndef __sparc__
@@ -2469,34 +2458,20 @@
 #endif
 	printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n",
 		(unsigned long)	mem_base, bufp);
-	printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
     
 	ohci = hc_alloc_ohci (dev, mem_base);
 	if (!ohci) {
 		return -ENOMEM;
 	}
+	ohci->slot_name = slot_name;
 	if ((ret = ohci_mem_init (ohci)) < 0) {
 		hc_release_ohci (ohci);
 		return ret;
 	}
-	ohci->flags = id->driver_data;
+	ohci->flags = flags;
 	if (ohci->flags & OHCI_QUIRK_AMD756)
 		printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
 
-	/* bad pci latencies can contribute to overruns */ 
-	pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
-	if (latency) {
-		pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
-		if (limit && limit < latency) {
-			dbg ("PCI latency reduced to max %d", limit);
-			pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
-			ohci->pci_latency = limit;
-		} else {
-			/* it might already have been reduced */
-			ohci->pci_latency = latency;
-		}
-	}
-
 	if (hc_reset (ohci) < 0) {
 		hc_release_ohci (ohci);
 		return -ENODEV;
@@ -2508,134 +2483,23 @@
 
 	usb_register_bus (ohci->bus);
 	
-	if (request_irq (irq, hc_interrupt, SA_SHIRQ,
-			ohci_pci_driver.name, ohci) != 0) {
+	if (request_irq (irq, hc_interrupt, SA_SHIRQ, name, ohci) != 0) {
 		err ("request interrupt %s failed", bufp);
 		hc_release_ohci (ohci);
 		return -EBUSY;
 	}
 	ohci->irq = irq;     
 
-	if (hc_start (ohci) < 0) {
-		err ("can't start usb-%s", dev->slot_name);
-		hc_release_ohci (ohci);
-		return -EBUSY;
-	}
+	*ohcip = ohci;
 
-#ifdef	DEBUG
-	ohci_dump (ohci, 1);
-#endif
 	return 0;
 }
 
-/*-------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_PM
-
-/* controller died; cleanup debris, then restart */
-/* must not be called from interrupt context */
-
-static void hc_restart (ohci_t *ohci)
-{
-	int temp;
-	int i;
-
-	if (ohci->pci_latency)
-		pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
-
-	ohci->disabled = 1;
-	ohci->sleeping = 0;
-	if (ohci->bus->root_hub)
-		usb_disconnect (&ohci->bus->root_hub);
-	
-	/* empty the interrupt branches */
-	for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
-	for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
-	
-	/* no EDs to remove */
-	ohci->ed_rm_list [0] = NULL;
-	ohci->ed_rm_list [1] = NULL;
-
-	/* empty control and bulk lists */	 
-	ohci->ed_isotail     = NULL;
-	ohci->ed_controltail = NULL;
-	ohci->ed_bulktail    = NULL;
-
-	if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 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);
-}
-
-#endif	/* CONFIG_PM */
-
-/*-------------------------------------------------------------------------*/
-
-/* configured so that an OHCI device is always provided */
-/* always called with process context; sleeping is OK */
-
-static int __devinit
-ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+/*
+ * Host bus independent remove one OHCI host controller.
+ */
+void hc_remove_ohci(ohci_t *ohci)
 {
-	unsigned long mem_resource, mem_len;
-	void *mem_base;
-	int status;
-
-	if (pci_enable_device(dev) < 0)
-		return -ENODEV;
-
-        if (!dev->irq) {
-        	err("found OHCI device with no IRQ assigned. check BIOS settings!");
-		pci_disable_device (dev);
-   	        return -ENODEV;
-        }
-	
-	/* we read its hardware registers as memory */
-	mem_resource = pci_resource_start(dev, 0);
-	mem_len = pci_resource_len(dev, 0);
-	if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
-		dbg ("controller already in use");
-		pci_disable_device (dev);
-		return -EBUSY;
-	}
-
-	mem_base = ioremap_nocache (mem_resource, mem_len);
-	if (!mem_base) {
-		err("Error mapping OHCI memory");
-		release_mem_region (mem_resource, mem_len);
-		pci_disable_device (dev);
-		return -EFAULT;
-	}
-
-	/* controller writes into our memory */
-	pci_set_master (dev);
-
-	status = hc_found_ohci (dev, dev->irq, mem_base, id);
-	if (status < 0) {
-		iounmap (mem_base);
-		release_mem_region (mem_resource, mem_len);
-		pci_disable_device (dev);
-	}
-	return status;
-} 
-
-/*-------------------------------------------------------------------------*/
-
-/* may be called from interrupt context [interface spec] */
-/* may be called without controller present */
-/* may be called with controller, bus, and devices active */
-
-static void __devexit
-ohci_pci_remove (struct pci_dev *dev)
-{
-	ohci_t		*ohci = pci_get_drvdata(dev);
-
-	dbg ("remove %s controller usb-%s%s%s",
-		hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
-		dev->slot_name,
-		ohci->disabled ? " (disabled)" : "",
-		in_interrupt () ? " in interrupt" : ""
-		);
 #ifdef	DEBUG
 	ohci_dump (ohci, 1);
 #endif
@@ -2652,270 +2516,16 @@
 			&ohci->regs->control);
 
 	hc_release_ohci (ohci);
-
-	release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
-	pci_disable_device (dev);
-}
-
-
-#ifdef	CONFIG_PM
-
-/*-------------------------------------------------------------------------*/
-
-static int
-ohci_pci_suspend (struct pci_dev *dev, u32 state)
-{
-	ohci_t			*ohci = pci_get_drvdata(dev);
-	unsigned long		flags;
-	u16 cmd;
-
-	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
-		dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
-			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
-		return -EIO;
-	}
-
-	/* act as if usb suspend can always be used */
-	info ("USB suspend: usb-%s", dev->slot_name);
-	ohci->sleeping = 1;
-
-	/* First stop processing */
-  	spin_lock_irqsave (&usb_ed_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 (&usb_ed_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 (ohci->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("Bus in reset phase ???");
-			break;
-		case OHCI_USB_RESUME:
-			dbg("Bus in resume phase ???");
-			break;
-		case OHCI_USB_OPER:
-			dbg("Bus in operational phase ???");
-			break;
-		case OHCI_USB_SUSPEND:
-			dbg("Bus suspended");
-			break;
-	}
-	/* In some rare situations, Apple's OHCI have happily trashed
-	 * memory during sleep. We disable it's bus master bit during
-	 * suspend
-	 */
-	pci_read_config_word (dev, PCI_COMMAND, &cmd);
-	cmd &= ~PCI_COMMAND_MASTER;
-	pci_write_config_word (dev, PCI_COMMAND, cmd);
-#ifdef CONFIG_PMAC_PBOOK
-	{
-		struct device_node	*of_node;
-
-		/* Disable USB PAD & cell clock */
-		of_node = pci_device_to_OF_node (ohci->ohci_dev);
-		if (of_node)
-			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
-	}
-#endif
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-ohci_pci_resume (struct pci_dev *dev)
-{
-	ohci_t		*ohci = pci_get_drvdata(dev);
-	int		temp;
-	unsigned long	flags;
-
-	/* guard against multiple resumes */
-	atomic_inc (&ohci->resume_count);
-	if (atomic_read (&ohci->resume_count) != 1) {
-		err ("concurrent PCI resumes for usb-%s", dev->slot_name);
-		atomic_dec (&ohci->resume_count);
-		return 0;
-	}
-
-#ifdef CONFIG_PMAC_PBOOK
-	{
-		struct device_node *of_node;
-
-		/* Re-enable USB PAD & cell clock */
-		of_node = pci_device_to_OF_node (ohci->ohci_dev);
-		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->ohci_dev);
-	
-	switch (temp) {
-
-	case OHCI_USB_RESET:	// lost power
-		info ("USB restart: usb-%s", dev->slot_name);
-		hc_restart (ohci);
-		break;
-
-	case OHCI_USB_SUSPEND:	// host wakeup
-	case OHCI_USB_RESUME:	// remote wakeup
-		info ("USB continue: usb-%s from %s wakeup", dev->slot_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 usb-%s won't resume", dev->slot_name);
-			ohci->disabled = 1;
-			return -EIO;
-		}
-
-		/* 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 (&usb_ed_lock, flags);
-		ohci->disabled = 0;
-		ohci->sleeping = 0;
-		ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
-		if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
-			if (ohci->ed_controltail)
-				ohci->hc_control |= OHCI_CTRL_CLE;
-			if (ohci->ed_bulktail)
-				ohci->hc_control |= OHCI_CTRL_BLE;
-		}
-		writel (ohci->hc_control, &ohci->regs->control);
-		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 (&usb_ed_lock, flags);
-#ifdef CONFIG_PMAC_PBOOK
-		if (_machine == _MACH_Pmac)
-			enable_irq (ohci->irq);
-#endif
-		if (ohci->hcca->done_head)
-			dl_done_list (ohci, dl_reverse_done_list (ohci));
-		writel (OHCI_INTR_WDH, &ohci->regs->intrenable); 
-		writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
-		writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
-		break;
-
-	default:
-		warn ("odd PCI resume for usb-%s", dev->slot_name);
-	}
-
-	/* controller is operational, extra resumes are harmless */
-	atomic_dec (&ohci->resume_count);
-
-	return 0;
-}
-
-#endif	/* CONFIG_PM */
-
-
-/*-------------------------------------------------------------------------*/
-
-static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
-
-	/*
-	 * AMD-756 [Viper] USB has a serious erratum when used with
-	 * lowspeed devices like mice.
-	 */
-	vendor:		0x1022,
-	device:		0x740c,
-	subvendor:	PCI_ANY_ID,
-	subdevice:	PCI_ANY_ID,
-
-	driver_data:	OHCI_QUIRK_AMD756,
-
-} , {
-
-	/* handle any USB OHCI controller */
-	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x10),
-	class_mask: 	~0,
-
-	/* 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, ohci_pci_ids);
-
-static struct pci_driver ohci_pci_driver = {
-	name:		"usb-ohci",
-	id_table:	&ohci_pci_ids [0],
-
-	probe:		ohci_pci_probe,
-	remove:		__devexit_p(ohci_pci_remove),
-
-#ifdef	CONFIG_PM
-	suspend:	ohci_pci_suspend,
-	resume:		ohci_pci_resume,
-#endif	/* PM */
-};
-
- 
-/*-------------------------------------------------------------------------*/
-
-static int __init ohci_hcd_init (void) 
-{
-	return pci_module_init (&ohci_pci_driver);
 }
 
-/*-------------------------------------------------------------------------*/
-
-static void __exit ohci_hcd_cleanup (void) 
-{	
-	pci_unregister_driver (&ohci_pci_driver);
-}
-
-module_init (ohci_hcd_init);
-module_exit (ohci_hcd_cleanup);
-
-
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(hc_add_ohci);
+EXPORT_SYMBOL(hc_remove_ohci);
+EXPORT_SYMBOL(hc_start);
+EXPORT_SYMBOL(hc_reset);
+EXPORT_SYMBOL(dl_done_list);
+EXPORT_SYMBOL(dl_reverse_done_list);
+EXPORT_SYMBOL(usb_ed_lock);
diff -Nru a/drivers/usb/host/usb-ohci.h b/drivers/usb/host/usb-ohci.h
--- a/drivers/usb/host/usb-ohci.h	Fri May 31 00:41:19 2002
+++ b/drivers/usb/host/usb-ohci.h	Fri May 31 00:41:19 2002
@@ -403,6 +403,7 @@
 
 	/* PCI device handle, settings, ... */
 	struct pci_dev	*ohci_dev;
+	const char	*slot_name;
 	u8		pci_latency;
 	struct pci_pool	*td_cache;
 	struct pci_pool	*dev_cache;
@@ -423,6 +424,10 @@
 // #define ohci_to_usb(ohci)	((ohci)->usb)
 #define usb_to_ohci(usb)	((struct ohci_device *)(usb)->hcpriv)
 
+/* For initializing controller (mask in an HCFS mode too) */
+#define OHCI_CONTROL_INIT \
+	(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
 /* hcd */
 /* endpoint */
 static int ep_link(ohci_t * ohci, ed_t * ed);
@@ -447,11 +452,6 @@
 #	define OHCI_MEM_FLAGS	0
 #endif
  
-#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 void *
@@ -640,4 +640,9 @@
 {
 	pci_pool_free (hc->dev_cache, dev, dev->dma);
 }
+
+extern spinlock_t usb_ed_lock;
+extern void dl_done_list (ohci_t * ohci, td_t * td_list);
+extern td_t * dl_reverse_done_list (ohci_t * ohci);
+
 
