static inline void ehci_ppc_soc_errata(struct ehci_hcd *ehci) { u32 hcc_params; struct ehci_spec_regs __iomem *spec_regs; if (!ehci) return; spec_regs = ehci->hcd.regs + SPEC_REGS_OFFSET; /* Enable Break Memory Transfer */ ehci_writel(ehci, EBMT, &spec_regs->insnreg03); /* * When park mode enabled, frame babble error occurs * due to high system latency. Disable park mode. */ hcc_params = ehci_readl (ehci, &ehci->caps->hcc_params); if (HCC_CANPARK(hcc_params)) { u32 cmd; cmd = ehci_readl (ehci, &ehci->regs->command); cmd &= ~CMD_PARK; ehci_writel (ehci, cmd, &ehci->regs->command); } }
/* one-time init, only for memory state */ static int ehci_init(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); u32 temp; int retval; u32 hcc_params; spin_lock_init(&ehci->lock); init_timer(&ehci->watchdog); ehci->watchdog.function = ehci_watchdog; ehci->watchdog.data = (unsigned long) ehci; init_timer(&ehci->iaa_watchdog); ehci->iaa_watchdog.function = ehci_iaa_watchdog; ehci->iaa_watchdog.data = (unsigned long) ehci; /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. */ ehci->periodic_size = DEFAULT_I_TDPS; INIT_LIST_HEAD(&ehci->cached_itd_list); if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) return retval; /* controllers may cache some of the periodic schedule ... */ hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); if (HCC_ISOC_CACHE(hcc_params)) // full frame cache ehci->i_thresh = 8; else // N microframes cached ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); ehci->reclaim = NULL; ehci->next_uframe = -1; ehci->clock_frame = -1; /* * dedicate a qh for the async ring head, since we couldn't unlink * a 'real' qh without stopping the async schedule [4.8]. use it * as the 'reclamation list head' too. * its dummy is used in hw_alt_next of many tds, to prevent the qh * from automatically advancing to the next td after short reads. */ ehci->async->qh_next.qh = NULL; ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); ehci->async->hw_qtd_next = EHCI_LIST_END(ehci); ehci->async->qh_state = QH_STATE_LINKED; ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma); /* clear interrupt enables, set irq latency */ if (log2_irq_thresh < 0 || log2_irq_thresh > 6) log2_irq_thresh = 0; temp = 1 << (16 + log2_irq_thresh); if (HCC_CANPARK(hcc_params)) { /* HW default park == 3, on hardware that supports it (like * NVidia and ALI silicon), maximizes throughput on the async * schedule by avoiding QH fetches between transfers. * * With fast usb storage devices and NForce2, "park" seems to * make problems: throughput reduction (!), data errors... */ if (park) { park = min(park, (unsigned) 3); temp |= CMD_PARK; temp |= park << 8; } ehci_dbg(ehci, "park %d\n", park); } if (HCC_PGM_FRAMELISTLEN(hcc_params)) { /* periodic schedule size can be smaller than default */ temp &= ~(3 << 2); temp |= (EHCI_TUNE_FLS << 2); switch (EHCI_TUNE_FLS) { case 0: ehci->periodic_size = 1024; break; case 1: ehci->periodic_size = 512; break; case 2: ehci->periodic_size = 256; break; default: BUG(); } } ehci->command = temp; return 0; }