(Sorry for this repost, apparently the mailserver reformats before sending.)

There is a published errata for the PPC440EPX, USBH_23: EHCI and OHCI
Linux module contention.  The overview states: When running Linux with
both EHCI and OHCI modules loaded, the EHCI module experiences a fatal
error when a high-speed device is connected to the USB2.0 Host controller.
The EHCI module functions normally when the OHCI module is not loaded.

The patch below is a software work around for the problem. I would like to
discuss the probability of the patch being accepted into the kernel and /
or what could be done to increase the probability.  The patch is against
the head of the DENX git repository, linux-2.6-denx.git.

Signed-off-by: Mark Miesfeld <[EMAIL PROTECTED]>

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 012954b..1569c8b 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -67,6 +67,26 @@ config USB_EHCI_TT_NEWSCHED

          If unsure, say N.

+config  USB_PPC440EPX_USBH_23_ERRATA
+       bool "PPC440EPX USBH_23 ERRATA EHCI and OHCI contention"
+       depends on USB_EHCI_HCD && 440EPX
+       default y
+       select USB_OHCI_HCD
+       select USB_OHCI_HCD_PPC_SOC
+       ---help---
+         Allows the EHCI and OHCI drivers to be loaded together when using
+         the USB Host controller on the 440EPX processor chip. This is
+         necessary when either high speed or full speed devices may be
+         connected to the USB Host port.  You must compile and use the OHCI
+         driver when selecting this option.
+
+         The option is not needed if the USB Host port is only used with
+         USB 2.0 high speed devices and the OHCI driver is not compiled or
+         loaded.
+
+         Say N when the OHCI driver for the 440EPX will not be compiled or
+         will not be loaded.  If unsure, say Y.
+
 config USB_EHCI_BIG_ENDIAN_MMIO
        bool
        depends on USB_EHCI_HCD
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 1813b7c..03516d4 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -289,6 +289,12 @@ static inline void remove_companion_file

 /*-------------------------------------------------------------------------*/

+#ifdef CONFIG_USB_PPC440EPX_USBH_23_ERRATA
+extern void ohci_ppc_set_hcfs(int state);
+#define HCFS_SUSPEND      0
+#define HCFS_OPERATIONAL  1
+#endif
+
 static int check_reset_complete (
        struct ehci_hcd *ehci,
        int             index,
@@ -319,8 +325,17 @@ static int check_reset_complete (
                port_status &= ~PORT_RWC_BITS;
                ehci_writel(ehci, port_status, status_reg);

-       } else
+#ifdef CONFIG_USB_PPC440EPX_USBH_23_ERRATA
+               /* ensure 440EPX ohci controller state is operational */
+               ohci_ppc_set_hcfs(HCFS_OPERATIONAL);
+#endif
+       } else {
                ehci_dbg (ehci, "port %d high speed\n", index + 1);
+#ifdef CONFIG_USB_PPC440EPX_USBH_23_ERRATA
+               /* ensure 440EPx ohci controller state is suspended */
+               ohci_ppc_set_hcfs(HCFS_SUSPEND);
+#endif
+       }

        return port_status;
 }
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index 1a2e177..7195311 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -20,6 +20,37 @@ #include <linux/signal.h>
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */

+#ifdef CONFIG_USB_PPC440EPX_USBH_23_ERRATA
+struct ohci_hcd        *cached_ohci = NULL;
+#define HCFS_SUSPEND      0
+#define HCFS_OPERATIONAL  1
+void ohci_ppc_set_hcfs(int state) {
+       u32 hc_control;
+
+       hc_control = (ohci_readl(cached_ohci, &cached_ohci->regs->control)
+                     & ~OHCI_CTRL_HCFS);
+
+       switch ( state )  {
+       case HCFS_SUSPEND:
+               hc_control |= OHCI_USB_SUSPEND;
+               break;
+       case HCFS_OPERATIONAL :
+               hc_control |= OHCI_USB_OPER;
+               break;
+
+       default:
+               /* this is unexpected, shoud never happen */
+               hc_control |= OHCI_USB_SUSPEND;
+               break;
+       }
+
+       /* write the new state and flush the write. */
+       ohci_writel(cached_ohci, hc_control, &cached_ohci->regs->control);
+       (void) ohci_readl(cached_ohci, &cached_ohci->regs->control);
+}
+EXPORT_SYMBOL (ohci_ppc_set_hcfs);
+#endif
+
 /**
  * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
  * Context: !in_interrupt()
@@ -76,9 +107,27 @@ static int usb_hcd_ppc_soc_probe(const s
        ohci_hcd_init(ohci);

        retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
-       if (retval == 0)
+       if (retval == 0) {
+#ifdef CONFIG_USB_PPC440EPX_USBH_23_ERRATA
+               /* At this point ohci_run has executed, the controller is
+                * running, the root ports set up, etc.  Now, put the core in
+                * the suspended state.  The ehci driver will bring it out of
+                * suspended state when / if a non-high speed USB device is
+                * attached to the USB Host port.
+                */
+               u32 hc_control;
+               cached_ohci = ohci;
+               spin_lock_irq(&ohci->lock);
+
+               hc_control = ohci_readl(ohci, &ohci->regs->control);
+               hc_control |= OHCI_USB_SUSPEND;
+               ohci_writel(ohci, hc_control, &ohci->regs->control);
+               (void) ohci_readl(ohci, &ohci->regs->control);
+
+               spin_unlock_irq(&ohci->lock);
+#endif
                return retval;
-
+       }
        pr_debug("Removing PPC-SOC USB Controller\n");

        iounmap(hcd->regs);

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to