diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2009-08-20 15:39:55 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-23 06:46:38 -0700 |
commit | aab2d4086a1876fcff282aa36e2d4a92aa9935c9 (patch) | |
tree | 3b1bb3d934bec91c44eaf61aadb6c624eb8dd9b3 | |
parent | 8d053c79f22462f55c02c8083580730b922cf7b4 (diff) | |
download | linux-3.10-aab2d4086a1876fcff282aa36e2d4a92aa9935c9.tar.gz linux-3.10-aab2d4086a1876fcff282aa36e2d4a92aa9935c9.tar.bz2 linux-3.10-aab2d4086a1876fcff282aa36e2d4a92aa9935c9.zip |
USB: ehci-dbgp: errata for EHCI debug controller initialization
On some EHCI usb debug controllers, the EHCI debug device will fail to
be seen after a port reset, after a warm reset. Two options exist to
get the device to initialize correctly.
Option 1 is to unplug and plug in the device.
Option 2 is to use the EHCI port test to get the usb debug device to
start talking again. At that point the debug controller port reset
will succeed.
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
CC: dbrownell@users.sourceforge.net
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/early/ehci-dbgp.c | 23 | ||||
-rw-r--r-- | include/linux/usb/ehci_def.h | 1 |
2 files changed, 23 insertions, 1 deletions
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index b88cb65b64e..f0a41c647be 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -478,10 +478,13 @@ int dbgp_external_startup(void) int devnum; struct usb_debug_descriptor dbgp_desc; int ret; - u32 ctrl, portsc; + u32 ctrl, portsc, cmd; int dbg_port = dbgp_phys_port; int tries = 3; + int reset_port_tries = 1; + int try_hard_once = 1; +try_port_reset_again: ret = dbgp_ehci_startup(); if (ret) return ret; @@ -490,6 +493,24 @@ int dbgp_external_startup(void) ret = ehci_wait_for_port(dbg_port); if (ret < 0) { portsc = readl(&ehci_regs->port_status[dbg_port - 1]); + if (!(portsc & PORT_CONNECT) && try_hard_once) { + /* Last ditch effort to try to force enable + * the debug device by using the packet test + * ehci command to try and wake it up. */ + try_hard_once = 0; + cmd = readl(&ehci_regs->command); + cmd &= ~CMD_RUN; + writel(cmd, &ehci_regs->command); + portsc = readl(&ehci_regs->port_status[dbg_port - 1]); + portsc |= PORT_TEST_PKT; + writel(portsc, &ehci_regs->port_status[dbg_port - 1]); + dbgp_ehci_status("Trying to force debug port online"); + mdelay(50); + dbgp_ehci_controller_reset(); + goto try_port_reset_again; + } else if (reset_port_tries--) { + goto try_port_reset_again; + } dbgp_printk("No device found in debug port\n"); return -EIO; } diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h index 1909d924f81..af4b86f3aca 100644 --- a/include/linux/usb/ehci_def.h +++ b/include/linux/usb/ehci_def.h @@ -105,6 +105,7 @@ struct ehci_regs { #define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ #define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ /* 19:16 for port testing */ +#define PORT_TEST_PKT (0x4<<16) /* Port Test Control - packet test */ #define PORT_LED_OFF (0<<14) #define PORT_LED_AMBER (1<<14) #define PORT_LED_GREEN (2<<14) |