Commit e261944f authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[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.
parent b533e812
...@@ -384,19 +384,25 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -384,19 +384,25 @@ static int hc_reset (struct ohci_hcd *ohci)
} }
udelay (1); udelay (1);
} }
/* now we're in the SUSPEND state ... must go OPERATIONAL
* within 2msec else HC enters RESUME
*/
return 0; return 0;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#define FI 0x2edf /* 12000 bits per frame (-1) */
#define LSTHRESH 0x628 /* lowspeed bit threshold */
/* Start an OHCI controller, set the BUS operational /* Start an OHCI controller, set the BUS operational
* enable interrupts * enable interrupts
* connect the virtual root hub * connect the virtual root hub
*/ */
static int hc_start (struct ohci_hcd *ohci) static int hc_start (struct ohci_hcd *ohci)
{ {
__u32 mask; u32 mask;
unsigned int fminterval;
struct usb_device *udev; struct usb_device *udev;
spin_lock_init (&ohci->lock); spin_lock_init (&ohci->lock);
...@@ -405,18 +411,27 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -405,18 +411,27 @@ static int hc_start (struct ohci_hcd *ohci)
/* Tell the controller where the control and bulk lists are /* Tell the controller where the control and bulk lists are
* The lists are empty now. */ * The lists are empty now. */
writel (0, &ohci->regs->ed_controlhead); writel (0, &ohci->regs->ed_controlhead);
writel (0, &ohci->regs->ed_bulkhead); writel (0, &ohci->regs->ed_bulkhead);
/* a reset clears this */ /* a reset clears this */
writel ((u32) ohci->hcca_dma, &ohci->regs->hcca); writel ((u32) ohci->hcca_dma, &ohci->regs->hcca);
fminterval = 0x2edf; /* force default fmInterval (we won't adjust it); init thresholds
writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); * for last FS and LS packets, reserve 90% for periodic.
fminterval |= ((((fminterval - 210) * 6) / 7) << 16); */
writel (fminterval, &ohci->regs->fminterval); writel ((((6 * (FI - 210)) / 7) << 16) | FI, &ohci->regs->fminterval);
writel (0x628, &ohci->regs->lsthresh); 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 */ /* start controller operations */
ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
...@@ -430,9 +445,10 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -430,9 +445,10 @@ static int hc_start (struct ohci_hcd *ohci)
#ifdef OHCI_USE_NPS #ifdef OHCI_USE_NPS
/* required for AMD-756 and some Mac platforms */ /* 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); &ohci->regs->roothub.a);
writel (RH_HS_LPSC, &ohci->regs->roothub.status); writel (RH_HS_LPSC, &ohci->regs->roothub.status);
writel (0, &ohci->regs->roothub.b);
#endif /* OHCI_USE_NPS */ #endif /* OHCI_USE_NPS */
// POTPGT delay is bits 24-31, in 2 ms units. // POTPGT delay is bits 24-31, in 2 ms units.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment