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); -------------------------------------------------------- CONFIDENTIALITY NOTICE: This e-mail message, including any attachments, is for the sole use of the intended recipient(s) and contains information that is confidential and proprietary to Applied Micro Circuits Corporation or its subsidiaries. It is to be used solely for the purpose of furthering the parties' business relationship. All unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies of the original message. ------------------------------------------------------------------------- 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