ChangeSet 1.1843.4.14, 2004/08/24 11:55:24-07:00, [EMAIL PROTECTED] [PATCH] USB OTG: ohci reset updates (2/5)
Generic OTG and reset support for OTG. - Declare and use a start_hnp() board-specific procedure. The OMAP implementation will come separately, it can't yet be configured. - When OTG is configured, implement the usb_bus_start_enum() hook; that just starts a root port reset. - When some task (usually khubd) resets a root port, make sure it takes the full 50 msec. The OHCI reset timer is in hardware, and the host may need to issue multiple resets to guard against concurrent resume. - For backward compatibility, don't kick in the new 50 msec logic unless it could be needed: without CONFIG_USB_SUSPEND, nothing will suspend so nothing could resume. Which is good, at least until we start to measure how long a reset takes ... it seems chip-specific. Signed-off-by: David Brownell <[EMAIL PROTECTED]> Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]> drivers/usb/host/ohci-hub.c | 94 +++++++++++++++++++++++++++++++++++++++++-- drivers/usb/host/ohci-omap.c | 1 drivers/usb/host/ohci-pci.c | 3 - drivers/usb/host/ohci-q.c | 3 - 4 files changed, 93 insertions(+), 8 deletions(-) diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c --- a/drivers/usb/host/ohci-hub.c 2004-08-26 16:42:31 -07:00 +++ b/drivers/usb/host/ohci-hub.c 2004-08-26 16:42:31 -07:00 @@ -435,6 +435,89 @@ /*-------------------------------------------------------------------------*/ +#ifdef CONFIG_USB_OTG + +static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + u32 status; + + if (!port) + return -EINVAL; + port--; + + /* start port reset before HNP protocol times out */ + status = ohci_readl(&ohci->regs->roothub.portstatus [port]); + if (!(status & RH_PS_CCS)) + return -ENODEV; + + /* khubd will finish the reset later */ + writel(RH_PS_PRS, &ohci->regs->roothub.portstatus [port]); + return 0; +} + +static void start_hnp(struct ohci_hcd *ohci); + +#else + +#define ohci_start_port_reset NULL + +#endif + +/*-------------------------------------------------------------------------*/ + + +/* See usb 7.1.7.5: root hubs must issue at least 50 msec reset signaling, + * not necessarily continuous ... to guard against resume signaling. + * The short timeout is safe for non-root hubs, and is backward-compatible + * with earlier Linux hosts. + */ +#ifdef CONFIG_USB_SUSPEND +#define PORT_RESET_MSEC 50 +#else +#define PORT_RESET_MSEC 10 +#endif + +/* this timer value might be vendor-specific ... */ +#define PORT_RESET_HW_MSEC 10 + +/* wrap-aware logic stolen from <linux/jiffies.h> */ +#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0) + +/* called from some task, normally khubd */ +static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port) +{ + u32 *portstat = &ohci->regs->roothub.portstatus [port]; + u32 temp; + u16 now = readl(&ohci->regs->fmnumber); + u16 reset_done = now + PORT_RESET_MSEC; + + /* build a "continuous enough" reset signal, with up to + * 3msec gap between pulses. scheduler HZ==100 must work; + * this might need to be deadline-scheduled. + */ + do { + /* spin until any current reset finishes */ + for (;;) { + temp = ohci_readl (portstat); + if (!(temp & RH_PS_PRS)) + break; + udelay (500); + } + + if (!(temp & RH_PS_CCS)) + break; + if (temp & RH_PS_PRSC) + writel (RH_PS_PRSC, portstat); + + /* start the next reset, sleep till it's probably done */ + writel (RH_PS_PRS, portstat); + msleep(PORT_RESET_HW_MSEC); + now = readl(&ohci->regs->fmnumber); + } while (tick_before(now, reset_done)); + /* caller synchronizes using PRSC */ +} + static int ohci_hub_control ( struct usb_hcd *hcd, u16 typeReq, @@ -533,6 +616,12 @@ wIndex--; switch (wValue) { case USB_PORT_FEAT_SUSPEND: +#ifdef CONFIG_USB_OTG + if (ohci->hcd.self.otg_port == (wIndex + 1) + && ohci->hcd.self.b_hnp_enable) + start_hnp(ohci); + else +#endif writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [wIndex]); break; @@ -541,10 +630,7 @@ &ohci->regs->roothub.portstatus [wIndex]); break; case USB_PORT_FEAT_RESET: - temp = ohci_readl (&ohci->regs->roothub.portstatus [wIndex]); - if (temp & RH_PS_CCS) - writel (RH_PS_PRS, - &ohci->regs->roothub.portstatus [wIndex]); + root_port_reset (ohci, wIndex); break; default: goto error; diff -Nru a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c --- a/drivers/usb/host/ohci-omap.c 2004-08-26 16:42:31 -07:00 +++ b/drivers/usb/host/ohci-omap.c 2004-08-26 16:42:31 -07:00 @@ -566,6 +566,7 @@ .hub_suspend = ohci_hub_suspend, .hub_resume = ohci_hub_resume, #endif + .start_port_reset = ohci_start_port_reset, }; /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c --- a/drivers/usb/host/ohci-pci.c 2004-08-26 16:42:31 -07:00 +++ b/drivers/usb/host/ohci-pci.c 2004-08-26 16:42:31 -07:00 @@ -242,6 +242,7 @@ .hub_suspend = ohci_hub_suspend, .hub_resume = ohci_hub_resume, #endif + .start_port_reset = ohci_start_port_reset, }; /*-------------------------------------------------------------------------*/ @@ -276,7 +277,7 @@ if (usb_disabled()) return -ENODEV; - printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name, + pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, sizeof (struct ed), sizeof (struct td)); return pci_module_init (&ohci_pci_driver); } diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c 2004-08-26 16:42:31 -07:00 +++ b/drivers/usb/host/ohci-q.c 2004-08-26 16:42:31 -07:00 @@ -900,9 +900,6 @@ /*-------------------------------------------------------------------------*/ -/* wrap-aware logic stolen from <linux/jiffies.h> */ -#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0) - /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) ------------------------------------------------------- SF.Net email is sponsored by Shop4tech.com-Lowest price on Blank Media 100pk Sonic DVD-R 4x for only $29 -100pk Sonic DVD+R for only $33 Save 50% off Retail on Ink & Toner - Free Shipping and Free Gift. http://www.shop4tech.com/z/Inkjet_Cartridges/9_108_r285 _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel