David, this patch comes from applying my original patch and making a
couple of changes to clean it up.  Almost all of it applied cleanly.
It isn't clear to me what changes you made to the code that should
have made this difficult.

> Looking forward to it, thanks!  I should be able to just
> sanity check it and forward ... the only issue with the previous
> one was conflicts with patches I'd just sent myself.  Please
> send it as a patch with that new "Signed-off-by:" line.

Signed-off-by: Marc Singer <[EMAIL PROTECTED]>

PATCH

diff -Nru a/drivers/usb/Kconfig b/drivers/usb/Kconfig
--- a/drivers/usb/Kconfig       Sat Jun  5 11:14:49 2004
+++ b/drivers/usb/Kconfig       Sat Jun  5 11:14:49 2004
@@ -7,7 +7,7 @@
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
 config USB
        tristate "Support for Host-side USB"
-       depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610
+       depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_LH7A404
        ---help---
          Universal Serial Bus (USB) is a specification for a serial bus
          subsystem which offers higher speeds and more features than the
diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- a/drivers/usb/host/ohci-dbg.c       Sat Jun  5 11:14:49 2004
+++ b/drivers/usb/host/ohci-dbg.c       Sat Jun  5 11:14:49 2004
@@ -134,13 +134,13 @@
        struct ohci_regs        *regs = controller->regs;
        u32                     temp;
 
-       temp = readl (&regs->revision) & 0xff;
+       temp = ohci_readl (&regs->revision) & 0xff;
        ohci_dbg_sw (controller, next, size,
                "OHCI %d.%d, %s legacy support registers\n",
                0x03 & (temp >> 4), (temp & 0x0f),
                (temp & 0x10) ? "with" : "NO");
 
-       temp = readl (&regs->control);
+       temp = ohci_readl (&regs->control);
        ohci_dbg_sw (controller, next, size,
                "control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
                temp,
@@ -155,7 +155,7 @@
                temp & OHCI_CTRL_CBSR
                );
 
-       temp = readl (&regs->cmdstatus);
+       temp = ohci_readl (&regs->cmdstatus);
        ohci_dbg_sw (controller, next, size,
                "cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp,
                (temp & OHCI_SOC) >> 16,
@@ -166,26 +166,26 @@
                );
 
        ohci_dump_intr_mask (controller, "intrstatus",
-                       readl (&regs->intrstatus), next, size);
+                       ohci_readl (&regs->intrstatus), next, size);
        ohci_dump_intr_mask (controller, "intrenable",
-                       readl (&regs->intrenable), next, size);
+                       ohci_readl (&regs->intrenable), next, size);
        // intrdisable always same as intrenable
 
        maybe_print_eds (controller, "ed_periodcurrent",
-                       readl (&regs->ed_periodcurrent), next, size);
+                       ohci_readl (&regs->ed_periodcurrent), next, size);
 
        maybe_print_eds (controller, "ed_controlhead",
-                       readl (&regs->ed_controlhead), next, size);
+                       ohci_readl (&regs->ed_controlhead), next, size);
        maybe_print_eds (controller, "ed_controlcurrent",
-                       readl (&regs->ed_controlcurrent), next, size);
+                       ohci_readl (&regs->ed_controlcurrent), next, size);
 
        maybe_print_eds (controller, "ed_bulkhead",
-                       readl (&regs->ed_bulkhead), next, size);
+                       ohci_readl (&regs->ed_bulkhead), next, size);
        maybe_print_eds (controller, "ed_bulkcurrent",
-                       readl (&regs->ed_bulkcurrent), next, size);
+                       ohci_readl (&regs->ed_bulkcurrent), next, size);
 
        maybe_print_eds (controller, "donehead",
-                       readl (&regs->donehead), next, size);
+                       ohci_readl (&regs->donehead), next, size);
 }
 
 #define dbg_port_sw(hc,num,value,next,size) \
@@ -637,7 +637,7 @@
                        "hcca frame 0x%04x\n", OHCI_FRAME_NO(ohci->hcca));
 
        /* other registers mostly affect frame timings */
-       rdata = readl (&regs->fminterval);
+       rdata = ohci_readl (&regs->fminterval);
        temp = scnprintf (next, size,
                        "fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
                        rdata, (rdata >> 31) ? " FIT" : "",
@@ -645,20 +645,20 @@
        size -= temp;
        next += temp;
 
-       rdata = readl (&regs->fmremaining);
+       rdata = ohci_readl (&regs->fmremaining);
        temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
                        rdata, (rdata >> 31) ? " FRT" : "",
                        rdata & 0x3fff);
        size -= temp;
        next += temp;
 
-       rdata = readl (&regs->periodicstart);
+       rdata = ohci_readl (&regs->periodicstart);
        temp = scnprintf (next, size, "periodicstart 0x%04x\n",
                        rdata & 0x3fff);
        size -= temp;
        next += temp;
 
-       rdata = readl (&regs->lsthresh);
+       rdata = ohci_readl (&regs->lsthresh);
        temp = scnprintf (next, size, "lsthresh 0x%04x\n",
                        rdata & 0x3fff);
        size -= temp;
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  5 11:14:49 2004
+++ b/drivers/usb/host/ohci-hcd.c       Sat Jun  5 11:14:49 2004
@@ -17,6 +17,7 @@
  *
  * History:
  * 
+ * 2004/03/24 LH7A404 support (Durgesh Pattamatta & Marc Singer)
  * 2004/02/04 use generic dma_* functions instead of pci_* ([EMAIL PROTECTED])
  * 2003/02/24 show registers in sysfs (Kevin Brosius)
  *
@@ -393,7 +394,7 @@
 
        /* boot firmware should have set this up (5.1.1.3.1) */
        if (!ohci->fminterval) {
-               temp = readl (&ohci->regs->fminterval);
+               temp = ohci_readl (&ohci->regs->fminterval);
                if (temp & 0x3fff0000)
                        ohci->fminterval = temp;
                else
@@ -405,7 +406,7 @@
         * On PA-RISC, PDC can leave IR set incorrectly; ignore it there.
         */
 #ifndef __hppa__
-       if (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+       if (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) {
                ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
 
                /* this timeout is arbitrary.  we make it long, so systems
@@ -416,7 +417,7 @@
 
                writel (OHCI_INTR_OC, &ohci->regs->intrenable);
                writel (OHCI_OCR, &ohci->regs->cmdstatus);
-               while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+               while (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) {
                        msleep (10);
                        if (--temp == 0) {
                                ohci_err (ohci, "USB HC TakeOver failed!\n");
@@ -430,13 +431,13 @@
        writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
 
        ohci_dbg (ohci, "reset, control = 0x%x\n",
-               readl (&ohci->regs->control));
+                 ohci_readl (&ohci->regs->control));
 
        /* Reset USB (needed by some controllers); RemoteWakeupConnected
         * saved if boot firmware (BIOS/SMM/...) told us it's connected
         * (for OHCI integrated on mainboard, it normally is)
         */
-       ohci->hc_control = readl (&ohci->regs->control);
+       ohci->hc_control = ohci_readl (&ohci->regs->control);
        ohci->hc_control &= OHCI_CTRL_RWC;      /* hcfs 0 = RESET */
        if (ohci->hc_control)
                ohci->hcd.can_wakeup = 1;
@@ -450,13 +451,13 @@
                                &ohci->regs->roothub.portstatus [temp]);
        }
        // flush those pci writes
-       (void) readl (&ohci->regs->control);
+       (void) ohci_readl (&ohci->regs->control);
        msleep (50);
 
        /* HC Reset requires max 10 us delay */
        writel (OHCI_HCR,  &ohci->regs->cmdstatus);
        temp = 30;      /* ... allow extra time */
-       while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+       while ((ohci_readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
                if (--temp == 0) {
                        ohci_err (ohci, "USB HC reset timed out!\n");
                        return -1;
@@ -473,7 +474,7 @@
         */
        writel (ohci->hc_control, &ohci->regs->control);
        // flush those pci writes
-       (void) readl (&ohci->regs->control);
+       (void) ohci_readl (&ohci->regs->control);
 
        return 0;
 }
@@ -505,8 +506,8 @@
        /* some OHCI implementations are finicky about how they init.
         * bogus values here mean not even enumeration could work.
         */
-       if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
-                       || !readl (&ohci->regs->periodicstart)) {
+       if ((ohci_readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
+                       || !ohci_readl (&ohci->regs->periodicstart)) {
                ohci_err (ohci, "init err\n");
                return -EOVERFLOW;
        }
@@ -548,7 +549,7 @@
        writel (RH_HS_LPSC, &ohci->regs->roothub.status);
        writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b);
        // flush those pci writes
-       (void) readl (&ohci->regs->control);
+       (void) ohci_readl (&ohci->regs->control);
 
        // POTPGT delay is bits 24-31, in 2 ms units.
        mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
@@ -592,19 +593,20 @@
        struct ohci_regs        *regs = ohci->regs;
        int                     ints; 
 
-       /* we can eliminate a (slow) readl() if _only_ WDH caused this irq */
+       /* we can eliminate a (slow) ohci_readl()
+          if _only_ WDH caused this irq */
        if ((ohci->hcca->done_head != 0)
                        && ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
                ints =  OHCI_INTR_WDH;
 
        /* cardbus/... hardware gone before remove() */
-       } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+       } else if ((ints = ohci_readl (&regs->intrstatus)) == ~(u32)0) {
                disable (ohci);
                ohci_dbg (ohci, "device removed!\n");
                return IRQ_HANDLED;
 
        /* interrupt for some other device? */
-       } else if ((ints &= readl (&regs->intrenable)) == 0) {
+       } else if ((ints &= ohci_readl (&regs->intrenable)) == 0) {
                return IRQ_NONE;
        } 
 
@@ -650,7 +652,7 @@
                writel (ints, &regs->intrstatus);
                writel (OHCI_INTR_MIE, &regs->intrenable);      
                // flush those pci writes
-               (void) readl (&ohci->regs->control);
+               (void) ohci_readl (&ohci->regs->control);
        }
 
        return IRQ_HANDLED;
@@ -798,6 +800,14 @@
 #include "ohci-omap.c"
 #endif
 
-#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111) || defined(CONFIG_ARCH_OMAP))
+#ifdef CONFIG_ARCH_LH7A404
+#include "ohci-lh7a404.c"
+#endif
+
+#if !(defined(CONFIG_PCI) \
+      || defined(CONFIG_SA1111) \
+      || defined(CONFIG_ARCH_OMAP) \
+      || defined (CONFIG_ARCH_LH7A404) \
+       )
 #error "missing bus glue for ohci-hcd"
 #endif
diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
--- a/drivers/usb/host/ohci-hub.c       Sat Jun  5 11:14:49 2004
+++ b/drivers/usb/host/ohci-hub.c       Sat Jun  5 11:14:49 2004
@@ -20,20 +20,20 @@
  * till some bits (mostly reserved) are clear; ok for all revs.
  */
 #define read_roothub(hc, register, mask) ({ \
-       u32 temp = readl (&hc->regs->roothub.register); \
+       u32 temp = ohci_readl (&hc->regs->roothub.register); \
        if (temp == -1) \
                disable (hc); \
        else if (hc->flags & OHCI_QUIRK_AMD756) \
                while (temp & mask) \
-                       temp = readl (&hc->regs->roothub.register); \
+                       temp = ohci_readl (&hc->regs->roothub.register); \
        temp; })
 
 static u32 roothub_a (struct ohci_hcd *hc)
        { return read_roothub (hc, a, 0xfc0fe000); }
 static inline u32 roothub_b (struct ohci_hcd *hc)
-       { return readl (&hc->regs->roothub.b); }
+       { return ohci_readl (&hc->regs->roothub.b); }
 static inline u32 roothub_status (struct ohci_hcd *hc)
-       { return readl (&hc->regs->roothub.status); }
+       { return ohci_readl (&hc->regs->roothub.status); }
 static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
        { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
 
@@ -332,7 +332,7 @@
                if (!HCD_IS_RUNNING(ohci->hcd.state))
                        return -ESHUTDOWN;
                ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n",
-                       ports, readl (&ohci->regs->roothub.a) & RH_A_NDP);
+                       ports, ohci_readl (&ohci->regs->roothub.a) & RH_A_NDP);
                /* retry later; "should not happen" */
                return 0;
        }
@@ -496,7 +496,7 @@
                        goto error;
                }
                writel (temp, &ohci->regs->roothub.portstatus [wIndex]);
-               // readl (&ohci->regs->roothub.portstatus [wIndex]);
+               // ohci_readl (&ohci->regs->roothub.portstatus [wIndex]);
                break;
        case GetHubDescriptor:
                ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
@@ -541,7 +541,7 @@
                                &ohci->regs->roothub.portstatus [wIndex]);
                        break;
                case USB_PORT_FEAT_RESET:
-                       temp = readl (&ohci->regs->roothub.portstatus [wIndex]);
+                       temp = ohci_readl (&ohci->regs->roothub.portstatus [wIndex]);
                        if (temp & RH_PS_CCS)
                                writel (RH_PS_PRS,
                                    &ohci->regs->roothub.portstatus [wIndex]);
diff -Nru a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
--- /dev/null   Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ohci-lh7a404.c   Sat Jun  5 11:14:49 2004
@@ -0,0 +1,387 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <[EMAIL PROTECTED]>
+ * (C) Copyright 2000-2002 David Brownell <[EMAIL PROTECTED]>
+ * (C) Copyright 2002 Hewlett-Packard Company
+ *
+ * Bus Glue for Sharp LH7A404
+ *
+ * Written by Christopher Hoover <[EMAIL PROTECTED]>
+ * Based on fragments of previous driver by Rusell King et al.
+ *
+ * Modified for LH7A404 from ohci-sa1111.c
+ *  by Durgesh Pattamatta <[EMAIL PROTECTED]>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/arch/hardware.h>
+
+
+extern int usb_disabled(void);
+
+/*-------------------------------------------------------------------------*/
+
+static void lh7a404_start_hc(struct platform_device *dev)
+{
+       printk(KERN_DEBUG __FILE__
+              ": starting LH7A404 OHCI USB Controller\n");
+
+       /*
+        * Now, carefully enable the USB clock, and take
+        * the USB host controller out of reset.
+        */
+       CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */
+       udelay(1000);
+       USBH_CMDSTATUS = OHCI_HCR;
+       
+       printk(KERN_DEBUG __FILE__
+                  ": Clock to USB host has been enabled \n");
+}
+
+static void lh7a404_stop_hc(struct platform_device *dev)
+{
+       printk(KERN_DEBUG __FILE__
+              ": stopping LH7A404 OHCI USB Controller\n");
+
+       CSC_PWRCNT &= ~CSC_PWRCNT_USBH_EN; /* Disable clock */
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+
+static irqreturn_t usb_hcd_lh7a404_hcim_irq (int irq, void *__hcd,
+                                            struct pt_regs * r)
+{
+       struct usb_hcd *hcd = __hcd;
+
+       return usb_hcd_irq(irq, hcd, r);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void usb_hcd_lh7a404_remove (struct usb_hcd *, struct platform_device *);
+
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
+
+
+/**
+ * usb_hcd_lh7a404_probe - initialize LH7A404-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.
+ *
+ */
+int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
+                         struct usb_hcd **hcd_out,
+                         struct platform_device *dev)
+{
+       int retval;
+       struct usb_hcd *hcd = 0;
+
+       unsigned int *addr = NULL;
+
+       if (!request_mem_region(dev->resource[0].start,
+                               dev->resource[0].end
+                               - dev->resource[0].start + 1, hcd_name)) {
+               pr_debug("request_mem_region failed");
+               return -EBUSY;
+       }
+       
+       
+       lh7a404_start_hc(dev);
+       
+       addr = ioremap(dev->resource[0].start,
+                      dev->resource[0].end
+                      - dev->resource[0].start + 1);
+       if (!addr) {
+               pr_debug("ioremap failed");
+               retval = -ENOMEM;
+               goto err1;
+       }
+       
+
+       hcd = driver->hcd_alloc ();
+       if (hcd == NULL){
+               pr_debug ("hcd_alloc failed");
+               retval = -ENOMEM;
+               goto err1;
+       }
+
+       if(dev->resource[1].flags != IORESOURCE_IRQ){
+               pr_debug ("resource[1] is not IORESOURCE_IRQ");
+               retval = -ENOMEM;
+               goto err1;
+       }
+
+       hcd->driver = (struct hc_driver *) driver;
+       hcd->description = driver->description;
+       hcd->irq = dev->resource[1].start;
+       hcd->regs = addr;
+       hcd->self.controller = &dev->dev;
+
+       retval = hcd_buffer_create (hcd);
+       if (retval != 0) {
+               pr_debug ("pool alloc fail");
+               goto err1;
+       }
+
+       retval = request_irq (hcd->irq, usb_hcd_lh7a404_hcim_irq, SA_INTERRUPT,
+                             hcd->description, hcd);
+       if (retval != 0) {
+               pr_debug("request_irq failed");
+               retval = -EBUSY;
+               goto err2;
+       }
+
+       pr_debug ("%s (LH7A404) at 0x%p, irq %d",
+            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 = "lh7a404";
+       hcd->product_desc = "LH7A404 OHCI";
+
+       INIT_LIST_HEAD (&hcd->dev_list);
+
+       usb_register_bus (&hcd->self);
+
+       if ((retval = driver->start (hcd)) < 0)
+       {
+               usb_hcd_lh7a404_remove(hcd, dev);
+               return retval;
+       }
+
+       *hcd_out = hcd;
+       return 0;
+
+ err2:
+       hcd_buffer_destroy (hcd);
+       if (hcd)
+               driver->hcd_free(hcd);
+ err1:
+       lh7a404_stop_hc(dev);
+       release_mem_region(dev->resource[0].start,
+                               dev->resource[0].end
+                          - dev->resource[0].start + 1);
+       return retval;
+}
+
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_hcd_lh7a404_remove - shutdown processing for LH7A404-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_lh7a404_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_lh7a404_remove (struct usb_hcd *hcd, struct platform_device *dev)
+{
+       struct usb_device       *hub;
+       void *base;
+
+       pr_debug ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
+
+       if (in_interrupt ())
+               BUG ();
+
+       hub = hcd->self.root_hub;
+       hcd->state = USB_STATE_QUIESCING;
+
+       pr_debug ("%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);
+       hcd_buffer_destroy (hcd);
+
+       usb_deregister_bus (&hcd->self);
+
+       base = hcd->regs;
+       hcd->driver->hcd_free (hcd);
+
+       lh7a404_stop_hc(dev);
+       release_mem_region(dev->resource[0].start,
+                          dev->resource[0].end
+                          - dev->resource[0].start + 1);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __devinit
+ohci_lh7a404_start (struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+       int             ret;
+
+       ohci_dbg (ohci, "ohci_lh7a404_start, ohci:%p", ohci);
+                       
+       ohci->hcca = dma_alloc_coherent (hcd->self.controller,
+                       sizeof *ohci->hcca, &ohci->hcca_dma, 0);
+       if (!ohci->hcca)
+               return -ENOMEM;
+
+       ohci_dbg (ohci, "ohci_lh7a404_start, ohci->hcca:%p",
+                       ohci->hcca);
+
+       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;
+       }
+       create_debug_files (ohci);
+
+#ifdef DEBUG
+       ohci_dump (ohci, 1);
+#endif /*DEBUG*/
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct hc_driver ohci_lh7a404_hc_driver = {
+       .description =          hcd_name,
+
+       /*
+        * generic hardware linkage
+        */
+       .irq =                  ohci_irq,
+       .flags =                HCD_USB11,
+
+       /*
+        * basic lifecycle operations
+        */
+       .start =                ohci_lh7a404_start,
+#ifdef CONFIG_PM
+       /* suspend:             ohci_lh7a404_suspend,  -- tbd */
+       /* resume:              ohci_lh7a404_resume,   -- tbd */
+#endif /*CONFIG_PM*/
+       .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,
+       .endpoint_disable =     ohci_endpoint_disable,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number =     ohci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data =      ohci_hub_status_data,
+       .hub_control =          ohci_hub_control,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int ohci_hcd_lh7a404_drv_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct usb_hcd *hcd = NULL;
+       int ret;
+
+       pr_debug ("In ohci_hcd_lh7a404_drv_probe");
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       ret = usb_hcd_lh7a404_probe(&ohci_lh7a404_hc_driver, &hcd, pdev);
+
+       if (ret == 0)
+               dev_set_drvdata(dev, hcd);
+
+       return ret;
+}
+
+static int ohci_hcd_lh7a404_drv_remove(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+       usb_hcd_lh7a404_remove(hcd, pdev);
+       dev_set_drvdata(dev, NULL);
+       return 0;
+}
+       /*TBD*/
+/*static int ohci_hcd_lh7a404_drv_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+       return 0;
+}
+static int ohci_hcd_lh7a404_drv_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+
+       return 0;
+}
+*/
+
+static struct device_driver ohci_hcd_lh7a404_driver = {
+       .name           = "lh7a404-ohci",
+       .bus            = &platform_bus_type,
+       .probe          = ohci_hcd_lh7a404_drv_probe,
+       .remove         = ohci_hcd_lh7a404_drv_remove,
+       /*.suspend      = ohci_hcd_lh7a404_drv_suspend, */
+       /*.resume       = ohci_hcd_lh7a404_drv_resume, */
+};
+
+static int __init ohci_hcd_lh7a404_init (void)
+{
+       pr_debug (DRIVER_INFO " (LH7A404)");
+       pr_debug ("block sizes: ed %d td %d\n",
+               sizeof (struct ed), sizeof (struct td));
+
+       return driver_register(&ohci_hcd_lh7a404_driver);
+}
+
+static void __exit ohci_hcd_lh7a404_cleanup (void)
+{
+       driver_unregister(&ohci_hcd_lh7a404_driver);
+}
+
+module_init (ohci_hcd_lh7a404_init);
+module_exit (ohci_hcd_lh7a404_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  5 11:14:49 2004
+++ b/drivers/usb/host/ohci-q.c Sat Jun  5 11:14:49 2004
@@ -321,7 +321,7 @@
                        if (!ed->hwNextED) {
                                ohci->hc_control &= ~OHCI_CTRL_CLE;
                                writel (ohci->hc_control, &ohci->regs->control);
-                               // a readl() later syncs CLE with the HC
+                               // a ohci_readl() later syncs CLE with the HC
                        } else
                                writel (le32_to_cpup (&ed->hwNextED),
                                        &ohci->regs->ed_controlhead);
@@ -345,7 +345,7 @@
                        if (!ed->hwNextED) {
                                ohci->hc_control &= ~OHCI_CTRL_BLE;
                                writel (ohci->hc_control, &ohci->regs->control);
-                               // a readl() later syncs BLE with the HC
+                               // a ohci_readl() later syncs BLE with the HC
                        } else
                                writel (le32_to_cpup (&ed->hwNextED),
                                        &ohci->regs->ed_bulkhead);
@@ -481,7 +481,7 @@
        writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
        writel (OHCI_INTR_SF, &ohci->regs->intrenable);
        // flush those writes, and get latest HCCA contents
-       (void) readl (&ohci->regs->control);
+       (void) ohci_readl (&ohci->regs->control);
 
        /* SF interrupt might get delayed; record the frame counter value that
         * indicates when the HC isn't looking at it, so concurrent unlinks
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h   Sat Jun  5 11:14:49 2004
+++ b/drivers/usb/host/ohci.h   Sat Jun  5 11:14:49 2004
@@ -429,3 +429,22 @@
 #      define ohci_vdbg(ohci, fmt, args...) do { } while (0)
 #endif
 
+#ifdef CONFIG_ARCH_LH7A404
+       /* Marc Singer: at the time this code was written, the LH7A404
+        * had a problem reading the USB host registers.  This
+        * implementation of the ohci_readl function performs the read
+        * twice as a work-around.
+        */
+static inline unsigned int ohci_readl (void* regs)
+{
+       *(volatile unsigned int*) regs;
+       return *(volatile unsigned int*) regs;
+}
+#else
+       /* Standard version of ohci_readl uses standard, platform
+        * specific implementation. */
+static inline unsigned int ohci_readl (void* regs)
+{
+       return readl (regs);
+}
+#endif


-------------------------------------------------------
This SF.Net email is sponsored by the new InstallShield X.
>From Windows to Linux, servers to mobile, InstallShield X is the one
installation-authoring solution that does it all. Learn more and
evaluate today! http://www.installshield.com/Dev2Dev/0504
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to