diff -Naur --exclude=CVS linux-2.4-orig/drivers/usb/Config.in linux-2.4-dev/drivers/usb/Config.in
--- linux-2.4-orig/drivers/usb/Config.in	Wed Sep 11 05:45:16 2002
+++ linux-2.4-dev/drivers/usb/Config.in	Sat Dec 28 17:41:19 2002
@@ -28,6 +28,7 @@
       define_bool CONFIG_USB_UHCI_ALT n
    fi
    dep_tristate '  OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
+   dep_tristate '    Non-PCI OHCI support' CONFIG_USB_NON_PCI_OHCI $CONFIG_USB_OHCI
 
    comment 'USB Device Class drivers'
    dep_tristate '  USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
diff -Naur --exclude=CVS linux-2.4-orig/drivers/usb/usb-ohci.c linux-2.4-dev/drivers/usb/usb-ohci.c
--- linux-2.4-orig/drivers/usb/usb-ohci.c	Wed Sep 11 05:45:19 2002
+++ linux-2.4-dev/drivers/usb/usb-ohci.c	Sat Dec 28 18:20:27 2002
@@ -2470,7 +2470,9 @@
 	void *mem_base, const struct pci_device_id *id)
 {
 	ohci_t * ohci;
+#ifndef CONFIG_USB_NON_PCI_OHCI
 	u8 latency, limit;
+#endif
 	char buf[8], *bufp = buf;
 	int ret;
 
@@ -2491,6 +2493,8 @@
 		hc_release_ohci (ohci);
 		return ret;
 	}
+
+#ifndef CONFIG_USB_NON_PCI_OHCI
 	ohci->flags = id->driver_data;
 	
 	/* Check for NSC87560. We have to look at the bridge (fn1) to identify
@@ -2523,7 +2527,8 @@
 			ohci->pci_latency = latency;
 		}
 	}
-
+#endif
+	
 	if (hc_reset (ohci) < 0) {
 		hc_release_ohci (ohci);
 		return -ENODEV;
@@ -2567,9 +2572,11 @@
 	int temp;
 	int i;
 
+#ifndef CONFIG_USB_NON_PCI_OHCI
 	if (ohci->pci_latency)
 		pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
-
+#endif
+	
 	ohci->disabled = 1;
 	ohci->sleeping = 0;
 	if (ohci->bus->root_hub)
@@ -2601,6 +2608,8 @@
 /* configured so that an OHCI device is always provided */
 /* always called with process context; sleeping is OK */
 
+#ifndef CONFIG_USB_NON_PCI_OHCI
+
 static int __devinit
 ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
 {
@@ -2646,6 +2655,90 @@
 	return status;
 } 
 
+#else  /* CONFIG_USB_NON_PCI_OHCI */
+
+// Boot options
+static int ohci_base=0, ohci_len=0;
+static int ohci_irq=-1;
+
+MODULE_PARM(ohci_base, "i");
+MODULE_PARM(ohci_len, "i");
+MODULE_PARM(ohci_irq, "i");
+MODULE_PARM_DESC(ohci_base, "IO Base address of OHCI Oper. registers");
+MODULE_PARM_DESC(ohci_len, "IO length of OHCI Oper. registers");
+MODULE_PARM_DESC(ohci_irq, "IRQ for OHCI interrupts");
+
+// bogus pci_dev
+static struct pci_dev bogus_pcidev;
+
+static struct pci_driver ohci_pci_driver = {
+	name:		"usb-ohci",
+};
+
+static int __devinit
+ohci_non_pci_init (void)
+{
+    void *mem_base;
+
+    if (!ohci_base || !ohci_len || (ohci_irq < 0))
+	return -ENODEV;
+    
+    if (!request_mem_region (ohci_base, ohci_len, ohci_pci_driver.name)) {
+	dbg ("controller already in use");
+	return -EBUSY;
+    }
+    
+    mem_base = ioremap_nocache (ohci_base, ohci_len);
+    if (!mem_base) {
+	err("Error mapping OHCI memory");
+	return -EFAULT;
+    }
+	
+    /*
+     * Fill in the bogus pci_dev. Only those members actually
+     * dereferenced in this driver are initialized.
+     */
+    memset(&bogus_pcidev, 0, sizeof(struct pci_dev));
+    strcpy(bogus_pcidev.name, "non-PCI OHCI");
+    strcpy(bogus_pcidev.slot_name, "builtin");
+    bogus_pcidev.resource[0].name = "OHCI Operational Registers";
+    bogus_pcidev.resource[0].start = ohci_base;
+    bogus_pcidev.resource[0].end = ohci_base + ohci_len;
+    bogus_pcidev.resource[0].flags = 0;
+    bogus_pcidev.irq = ohci_irq;
+
+    return hc_found_ohci (&bogus_pcidev, bogus_pcidev.irq, mem_base, NULL);
+} 
+
+#ifndef MODULE
+
+static int __init
+ohci_setup (char* options)
+{
+    char* this_opt;
+
+    if (!options || !*options)
+	return 0;
+
+    for(this_opt=strtok(options, ","); this_opt; this_opt=strtok(NULL, ",")) {
+	if (!strncmp(this_opt, "base:", 5)) {
+	    ohci_base = simple_strtoul(this_opt+5, NULL, 0);
+	} else if (!strncmp(this_opt, "len:", 4)) {
+	    ohci_len = simple_strtoul(this_opt+4, NULL, 0);
+	} else if (!strncmp(this_opt, "irq:", 4)) {
+	    ohci_irq = simple_strtoul(this_opt+4, NULL, 0);
+	}
+    }
+
+    return 0;
+}
+
+__setup("usb_ohci=", ohci_setup);
+
+#endif  /* !MODULE */
+
+#endif  /* CONFIG_USB_NON_PCI_OHCI */
+
 /*-------------------------------------------------------------------------*/
 
 /* may be called from interrupt context [interface spec] */
@@ -2685,6 +2778,8 @@
 }
 
 
+#ifndef CONFIG_USB_NON_PCI_OHCI
+
 #ifdef	CONFIG_PM
 
 /*-------------------------------------------------------------------------*/
@@ -2924,19 +3019,29 @@
 #endif	/* PM */
 };
 
- 
+#endif /* CONFIG_USB_NON_PCI_OHCI */
+
+
 /*-------------------------------------------------------------------------*/
 
 static int __init ohci_hcd_init (void) 
 {
+#ifndef CONFIG_USB_NON_PCI_OHCI
 	return pci_module_init (&ohci_pci_driver);
+#else
+	return ohci_non_pci_init();
+#endif
 }
 
 /*-------------------------------------------------------------------------*/
 
 static void __exit ohci_hcd_cleanup (void) 
 {	
+#ifndef CONFIG_USB_NON_PCI_OHCI
 	pci_unregister_driver (&ohci_pci_driver);
+#else
+	ohci_pci_remove(&bogus_pcidev);
+#endif
 }
 
 module_init (ohci_hcd_init);
diff -Naur --exclude=CVS linux-2.4-orig/drivers/usb/usb-ohci.h linux-2.4-dev/drivers/usb/usb-ohci.h
--- linux-2.4-orig/drivers/usb/usb-ohci.h	Wed Sep 11 05:45:19 2002
+++ linux-2.4-dev/drivers/usb/usb-ohci.h	Sat Dec 28 18:20:27 2002
@@ -449,8 +449,8 @@
 #endif
  
 #ifndef CONFIG_PCI
-#	error "usb-ohci currently requires PCI-based controllers"
-	/* to support non-PCI OHCIs, you need custom bus/mem/... glue */
+#	error "usb-ohci supports non-PCI based controllers,"
+#       error "but still requires PCI APIs."
 #endif
 
 
