/* * ehci_brcm_wait_for_sof * Wait for start of next microframe, then wait extra delay microseconds
*/ staticinlinevoid ehci_brcm_wait_for_sof(struct ehci_hcd *ehci, u32 delay)
{
u32 frame_idx = ehci_readl(ehci, &ehci->regs->frame_index);
u32 val; int res;
/* Wait for next microframe (every 125 usecs) */
res = readl_relaxed_poll_timeout(&ehci->regs->frame_index, val,
val != frame_idx, 1, 130); if (res)
ehci_err(ehci, "Error waiting for SOF\n");
udelay(delay);
}
/* * ehci_brcm_hub_control * The EHCI controller has a bug where it can violate the SOF * interval between the first two SOF's transmitted after resume * if the resume occurs near the end of the microframe. This causees * the controller to detect babble on the suspended port and * will eventually cause the controller to reset the port. * The fix is to Intercept the echi-hcd request to complete RESUME and * align it to the start of the next microframe. * See SWLINUX-1909 for more details
*/ staticint ehci_brcm_hub_control( struct usb_hcd *hcd,
u16 typeReq,
u16 wValue,
u16 wIndex, char *buf,
u16 wLength)
{ struct ehci_hcd *ehci = hcd_to_ehci(hcd); int ports = HCS_N_PORTS(ehci->hcs_params);
u32 __iomem *status_reg; unsignedlong flags; int retval, irq_disabled = 0;
u32 temp;
/* * RESUME is cleared when GetPortStatus() is called 20ms after start * of RESUME
*/ if ((typeReq == GetPortStatus) &&
(wIndex && wIndex <= ports) &&
ehci->reset_done[wIndex-1] &&
time_after_eq(jiffies, ehci->reset_done[wIndex-1]) &&
(ehci_readl(ehci, status_reg) & PORT_RESUME)) {
/* * to make sure we are not interrupted until RESUME bit * is cleared, disable interrupts on current CPU
*/
ehci_dbg(ehci, "SOF alignment workaround\n");
irq_disabled = 1;
local_irq_save(flags);
ehci_brcm_wait_for_sof(ehci, 5);
}
retval = ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); if (irq_disabled)
local_irq_restore(flags); return retval;
}
/* This fixes the lockup during reboot due to prior interrupts */
ehci_writel(ehci, CMD_RESET, &ehci->regs->command);
mdelay(10);
/* * SWLINUX-1705: Avoid OUT packet underflows during high memory * bus usage
*/
ehci_writel(ehci, 0x00800040, &ehci->regs->brcm_insnreg[1]);
ehci_writel(ehci, 0x00000001, &ehci->regs->brcm_insnreg[3]);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.