# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.479 -> 1.480 # drivers/usb/host/ohci-hcd.c 1.14 -> 1.15 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/06/12 david-b@pacbell.net 1.480 # [PATCH] ohci-hcd init err detect # # I tracked down some of those "can't enumerate" problems to a # chip init problem. This patch detects and reports that case # (better than the current nasty failure mode, and worth keeping # even after we have a fix that works on OPTi/SiS/...) as well as # doing some other minor cleanup. # -------------------------------------------- # diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c Fri Jun 14 14:15:37 2002 +++ b/drivers/usb/host/ohci-hcd.c Fri Jun 14 14:15:37 2002 @@ -374,29 +374,35 @@ /* Reset USB (needed by some controllers) */ writel (0, &ohci->regs->control); - + /* HC Reset requires max 10 ms delay */ writel (OHCI_HCR, &ohci->regs->cmdstatus); while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { if (--timeout == 0) { err ("USB HC reset timed out!"); return -1; - } + } udelay (1); } + + /* now we're in the SUSPEND state ... must go OPERATIONAL + * within 2msec else HC enters RESUME + */ return 0; } /*-------------------------------------------------------------------------*/ +#define FI 0x2edf /* 12000 bits per frame (-1) */ +#define LSTHRESH 0x628 /* lowspeed bit threshold */ + /* Start an OHCI controller, set the BUS operational * enable interrupts * connect the virtual root hub */ static int hc_start (struct ohci_hcd *ohci) { - __u32 mask; - unsigned int fminterval; + u32 mask; struct usb_device *udev; spin_lock_init (&ohci->lock); @@ -405,24 +411,33 @@ /* Tell the controller where the control and bulk lists are * The lists are empty now. */ - writel (0, &ohci->regs->ed_controlhead); writel (0, &ohci->regs->ed_bulkhead); - + /* a reset clears this */ writel ((u32) ohci->hcca_dma, &ohci->regs->hcca); - - fminterval = 0x2edf; - writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); - fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - writel (fminterval, &ohci->regs->fminterval); - writel (0x628, &ohci->regs->lsthresh); + + /* force default fmInterval (we won't adjust it); init thresholds + * for last FS and LS packets, reserve 90% for periodic. + */ + writel ((((6 * (FI - 210)) / 7) << 16) | FI, &ohci->regs->fminterval); + writel (((9 * FI) / 10) & 0x3fff, &ohci->regs->periodicstart); + writel (LSTHRESH, &ohci->regs->lsthresh); + + /* 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)) { + err ("%s init err", ohci->hcd.self.bus_name); + return -EOVERFLOW; + } /* start controller operations */ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; ohci->disabled = 0; writel (ohci->hc_control, &ohci->regs->control); - + /* Choose the interrupts we care about now, others later on demand */ mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH; writel (mask, &ohci->regs->intrstatus); @@ -430,9 +445,10 @@ #ifdef OHCI_USE_NPS /* required for AMD-756 and some Mac platforms */ - writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, + writel ((roothub_a (ohci) | RH_A_NPS) & ~(RH_A_PSM | RH_A_OCPM), &ohci->regs->roothub.a); writel (RH_HS_LPSC, &ohci->regs->roothub.status); + writel (0, &ohci->regs->roothub.b); #endif /* OHCI_USE_NPS */ // POTPGT delay is bits 24-31, in 2 ms units.