📄 ehci-hcd-fotg2xx.c
字号:
//Add Einsn@VIA#if 1 ehci->i_thresh = 8;#else 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);#endif//End Add ehci->reclaim = 0; ehci->next_uframe = -1; /* controller state: unknown --> reset *///printk("ehci_start4\n"); /* EHCI spec section 4.1 */ if ((retval = ehci_reset (ehci)) != 0) { ehci_mem_cleanup (ehci); return retval; } writel (INTR_MASK, &ehci->regs->intr_enable); writel (ehci->periodic_dma, &ehci->regs->frame_list); /* * 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 = 0; ehci->async->hw_next = QH_NEXT (ehci->async->qh_dma); ehci->async->hw_info1 = cpu_to_le32 (QH_HEAD); ehci->async->hw_token = cpu_to_le32 (QTD_STS_HALT); ehci->async->hw_qtd_next = EHCI_LIST_END; ehci->async->qh_state = QH_STATE_LINKED; ehci->async->hw_alt_next = QTD_NEXT (ehci->async->dummy->qtd_dma); writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); /* * hcc_params controls whether ehci->regs->segment must (!!!) * be used; it constrains QH/ITD/SITD and QTD locations. * pci_pool consistent memory always uses segment zero. * streaming mappings for I/O buffers, like pci_map_single(), * can return segments above 4GB, if the device allows. * * NOTE: the dma mask is visible through dma_supported(), so * drivers can pass this info along ... like NETIF_F_HIGHDMA, * Scsi_Host.highmem_io, and so forth. It's readonly to all * host side drivers though. *///Add Einsn@VIA#if 0 if (HCC_64BIT_ADDR (hcc_params)) { writel (0, &ehci->regs->segment); if (!pci_set_dma_mask (ehci->hcd.pdev, 0xffffffffffffffffULL)) ehci_info (ehci, "enabled 64bit PCI DMA\n"); }#endif //printk("ehci_start5\n"); /* help hc dma work well with cachelines */// pci_set_mwi (ehci->hcd.pdev); /* clere has no member upt enables, set irq latency */ temp = readl (&ehci->regs->command) & 0xff; if (log2_irq_thresh < 0 || log2_irq_thresh > 6) log2_irq_thresh = 0; temp |= 1 << (16 + log2_irq_thresh);//Einsn Mask <002> 2007-05-22 #if 0 // if hc can park (ehci >= 0.96), default is 3 packets per async QH 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 (); } }#endif temp &= ~(CMD_IAAD | CMD_ASE | CMD_PSE), // Philips, Intel, and maybe others need CMD_RUN before the // root hub will detect new devices (why?); NEC doesn't//Add Einsn@VIA#if 0 temp |= CMD_RUN;#endif writel (temp, &ehci->regs->command); dbg_cmd (ehci, "init", temp); /* set async sleep time = 10 us ... ? */ init_timer (&ehci->watchdog); ehci->watchdog.function = ehci_watchdog; ehci->watchdog.data = (unsigned long) ehci;//printk("ehci_start6\n"); /* wire up the root hub */ bus = hcd_to_bus (hcd); bus->root_hub = udev = usb_alloc_dev (NULL, bus); if (!udev) {done2: ehci_mem_cleanup (ehci); return -ENOMEM; } /* * Start, enabling full USB 2.0 functionality ... usb 1.1 devices * are explicitly handed to companion controller(s), so no TT is * involved with the root hub. */ ehci->hcd.state = USB_STATE_READY;//Add Einsn@VIA#if 0 writel (FLAG_CF, &ehci->regs->configured_flag);#endif readl (&ehci->regs->command); /* unblock posted write */ /* PCI Serial Bus Release Number is at 0x60 offset *///Einsn@VIA pci_read_config_byte (hcd->pdev, 0x60, &tempbyte); temp = readw (&ehci->caps->hci_version);//Einsn Mask <003> 2007-05-22 /* ehci_info (ehci, "USB %x.%x enabled, EHCI %x.%02x, driver %s\n", ((tempbyte & 0xf0)>>4), (tempbyte & 0x0f), temp >> 8, temp & 0xff, DRIVER_VERSION);*/ /* * From here on, khubd concurrently accesses the root * hub; drivers will be talking to enumerated devices. * * Before this point the HC was idle/ready. After, khubd * and device drivers may start it running. *///printk("ehci_start7\n"); usb_connect (udev); udev->speed = USB_SPEED_HIGH;//Start;;Faraday-EHCI(FOTG2XX) ehci->hcd.bus->otg_port = 1;//Faraday OTG dafault port=1 printk("Set OTG port=1\n");//End;;Faraday-EHCI(FOTG2XX) if (hcd_register_root (hcd) != 0) { if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); ehci_reset (ehci); bus->root_hub = 0; retval = -ENODEV; goto done2; } create_debug_files (ehci);//*** Connect Host to OTG //For OTG//Start;;Faraday-EHCI(FOTG2XX) //Init otg port ehci->transceiver = FOTG2XX_get_otg_transceiver(); if (ehci->transceiver) { int status = otg_set_host(ehci->transceiver,ehci->hcd.bus); DBG_HOST_EHCI("init %s transceiver, status %d\n", ehci->transceiver->label, status); if (status) { if (ehci->transceiver) printk("??? HCD=>otg_set_host fail ...\n"); return status; } } else { printk("can't find transceiver\n"); return -ENODEV; }//End;;Faraday-EHCI(FOTG2XX) return 0;}/* always called by thread; normally rmmod */static void ehci_stop (struct usb_hcd *hcd){ struct ehci_hcd *ehci = hcd_to_ehci (hcd); ehci_dbg (ehci, "stop\n"); /* no more interrupts ... */ if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); if (in_interrupt ()) { /* must not happen!! */ ehci_err (ehci, "stopped in_interrupt!\n"); return; } del_timer_sync (&ehci->watchdog); ehci_reset (ehci);//Einsn Mask <002> 2007-05-22 #if 0 /* let companion controllers work when we aren't */ writel (0, &ehci->regs->configured_flag);#endif remove_debug_files (ehci); /* root hub is shut down separately (first, when possible) */ spin_lock_irq (&ehci->lock); ehci_work (ehci, NULL); spin_unlock_irq (&ehci->lock); ehci_mem_cleanup (ehci);#ifdef EHCI_STATS ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld\n", ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim); ehci_dbg (ehci, "complete %ld unlink %ld\n", ehci->stats.complete, ehci->stats.unlink);#endif dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));}static int ehci_get_frame (struct usb_hcd *hcd){ struct ehci_hcd *ehci = hcd_to_ehci (hcd); return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;}/*-------------------------------------------------------------------------*/#ifdef CONFIG_PM/* suspend/resume, section 4.3 */static int ehci_suspend (struct usb_hcd *hcd, u32 state){ struct ehci_hcd *ehci = hcd_to_ehci (hcd); int ports; int i; dbg ("%s: suspend to %d", hcd_to_bus (hcd)->bus_name, state); ports = HCS_N_PORTS (ehci->hcs_params); // FIXME: This assumes what's probably a D3 level suspend... // FIXME: usb wakeup events on this bus should resume the machine. // pci config register PORTWAKECAP controls which ports can do it; // bios may have initted the register... /* suspend each port, then stop the hc */ for (i = 0; i < ports; i++) { int temp = readl (&ehci->regs->port_status [i]);#if 0 if (((temp & PORT_PE) == 0)) continue;#else if ((temp & PORT_PE) == 0 || (temp & PORT_OWNER) != 0) continue; #endifdbg ("%s: suspend port %d", hcd_to_bus (hcd)->bus_name, i);/*Einsn@VIA */ temp |= PORT_SUSPEND;/*Einsn@VIA */ writel (temp, &ehci->regs->port_status [i]); } if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); writel (readl (&ehci->regs->command) & ~CMD_RUN, &ehci->regs->command);// save pci FLADJ value /* who tells PCI to reduce power consumption? */ return 0;}static int ehci_resume (struct usb_hcd *hcd){ struct ehci_hcd *ehci = hcd_to_ehci (hcd); int ports; int i; dbg ("%s: resume", hcd_to_bus (hcd)->bus_name); ports = HCS_N_PORTS (ehci->hcs_params); // FIXME: if controller didn't retain state, // return and let generic code clean it up // test configured_flag ? /* resume HC and each port */// restore pci FLADJ value // khubd and drivers will set HC running, if needed; hcd->state = USB_STATE_READY; // FIXME Philips/Intel/... etc don't really have a "READY" // state ... turn on CMD_RUN too for (i = 0; i < ports; i++) { int temp = readl (&ehci->regs->port_status [i]);#if 0 if (((temp & PORT_PE) == 0)) continue;#else if ((temp & PORT_PE) == 0 || (temp & PORT_SUSPEND) != 0) continue;#endif dbg ("%s: resume port %d", hcd_to_bus (hcd)->bus_name, i); temp |= PORT_RESUME; writel (temp, &ehci->regs->port_status [i]); readl (&ehci->regs->command); /* unblock posted writes */ wait_ms (20); temp &= ~PORT_RESUME; writel (temp, &ehci->regs->port_status [i]); } readl (&ehci->regs->command); /* unblock posted writes */ return 0;}#endif//Start;;Faraday-EHCI(FOTG2XX)static int ehci_disconnect_for_OTG (struct usb_hcd *hcd, u32 state){ struct ehci_hcd *ehci = hcd_to_ehci (hcd); int ports; int i,iTemp; DBG_HOST_EHCI("### >>> Enter ehci-hcd.c file --> ehci_disconnect_for_OTG function \n"); ports = HCS_N_PORTS (ehci->hcs_params); // FIXME: This assumes what's probably a D3 level suspend... // FIXME: usb wakeup events on this bus should resume the machine. // pci config register PORTWAKECAP controls which ports can do it; // bios may have initted the register... /* suspend each port, then stop the hc */ for (i = 0; i < ports; i++) { int temp = readl (&ehci->regs->port_status [i]); if (((temp & PORT_PE) == 0)) continue; dbg ("%s: suspend port %d", hcd->bus_name, i); //Bruce;;04212005;; temp |= PORT_SUSPEND; //Bruce;;04212005;; writel (temp, &ehci->regs->port_status [i]); } if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS)) udelay (100); writel (readl (&ehci->regs->command) & ~CMD_RUN, &ehci->regs->command);#if 0 iTemp = readl (&ehci->regs->port_status [0]); if (iTemp&PORT_RESUME) { printk("TEMP===========> Detected the PORT_RESUME signal...\n"); iTemp &= ~PORT_RESUME; writel (iTemp, &ehci->regs->port_status [0]); }#endif#if 1 //Suspend the host;; iTemp = readl (&ehci->regs->port_status [0]); iTemp |= PORT_SUSPEND; writel (iTemp, &ehci->regs->port_status [0]);#endif return 0;}//End;;Faraday-EHCI(FOTG2XX)/*-------------------------------------------------------------------------*//* * ehci_work is called from some interrupts, timers, and so on. * it calls driver completion functions, after dropping ehci->lock. */static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs){ if (ehci->reclaim_ready) end_unlink_async (ehci, regs); scan_async (ehci, regs); if (ehci->next_uframe != -1) scan_periodic (ehci, regs);}/*-------------------------------------------------------------------------*/static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs){ struct ehci_hcd *ehci = hcd_to_ehci (hcd); u32 status; int bh; spin_lock (&ehci->lock); status = readl (&ehci->regs->status); /* e.g. cardbus physical eject */ if (status == ~(u32) 0) { ehci_dbg (ehci, "device removed\n"); goto dead; } status &= INTR_MASK; if (!status) /* irq sharing? */ goto done; /* clear (just) interrupts */ writel (status, &ehci->regs->status);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -