int ohci_power(void *ohci, int is_on) { struct ohci_hcd *ohcip = (struct ohci_hcd *)ohci; int port; int temp; temp = roothub_a(ohcip); /* If NoPowerSwitching is true, just return */ if (temp & RH_A_NPS) { return 0; } /* If port switched, switch each port */ if (temp & RH_A_PSM) { for (port = ohcip->num_ports; port > 0; ) { (void) ohci_hub_control(ohci_to_hcd(ohcip), is_on ? SetPortFeature : ClearPortFeature, USB_PORT_FEAT_POWER, port--, NULL, 0); } } /* Else use Global Power */ else { temp = roothub_status(ohcip); if (is_on) { temp |= RH_HS_LPSC; /* SetGlobalPower */ } else { temp |= RH_HS_LPS; /* ClearGlobalPower */ } ohci_writel(ohcip, temp, &ohcip->regs->roothub.status); } return 0; }
static int ohci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int i, changed = 0, length = 1; int can_suspend; unsigned long flags; can_suspend = device_may_wakeup(&hcd->self.root_hub->dev); spin_lock_irqsave (&ohci->lock, flags); /* handle autosuspended root: finish resuming before * letting khubd or root hub timer see state changes. */ if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER || !HC_IS_RUNNING(hcd->state))) { can_suspend = 0; goto done; } /* undocumented erratum seen on at least rev D */ if ((ohci->flags & OHCI_QUIRK_AMD756) && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) { ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n", ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ goto done; } /* init status */ if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) buf [0] = changed = 1; else buf [0] = 0; if (ohci->num_ports > 7) { buf [1] = 0; length++; } /* look at each port */ for (i = 0; i < ohci->num_ports; i++) { u32 status = roothub_portstatus (ohci, i); /* can't autosuspend with active ports */ if ((status & RH_PS_PES) && !(status & RH_PS_PSS)) can_suspend = 0; if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC)) { changed = 1; if (i < 7) buf [0] |= 1 << (i + 1); else buf [1] |= 1 << (i - 7); continue; } } /* after root hub changes, stop polling after debouncing * for a while and maybe kicking in autosuspend */ if (changed) { ohci->next_statechange = jiffies + STATECHANGE_DELAY; can_suspend = 0; } else if (time_before (jiffies, ohci->next_statechange)) { can_suspend = 0; } else { #ifdef CONFIG_PM can_suspend = can_suspend && !ohci->ed_rm_list && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) & ohci->hc_control) == OHCI_USB_OPER; #endif if (hcd->uses_new_polling) { hcd->poll_rh = 0; /* use INTR_RHSC iff INTR_RD won't apply */ if (!can_suspend) ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); } } done: spin_unlock_irqrestore (&ohci->lock, flags); #ifdef CONFIG_PM /* save power by autosuspending idle root hubs; * INTR_RD wakes us when there's work */ if (can_suspend && usb_trylock_device (hcd->self.root_hub) == 0) { ohci_vdbg (ohci, "autosuspend\n"); (void) ohci_bus_suspend (hcd); usb_unlock_device (hcd->self.root_hub); } #endif return changed ? length : 0; }
static int ohci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ports, i, changed = 0, length = 1; int can_suspend = hcd->can_wakeup; unsigned long flags; spin_lock_irqsave (&ohci->lock, flags); // hack by cfyeh for usb suspend/resume if(usb_ehci_suspend_flag == 1) { can_suspend = 0; goto done; } /* handle autosuspended root: finish resuming before * letting khubd or root hub timer see state changes. */ if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER || !HC_IS_RUNNING(hcd->state)) { can_suspend = 0; goto done; } ports = roothub_a (ohci) & RH_A_NDP; if (ports > MAX_ROOT_PORTS) { ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ goto done; } /* init status */ if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) buf [0] = changed = 1; else buf [0] = 0; if (ports > 7) { buf [1] = 0; length++; } /* look at each port */ for (i = 0; i < ports; i++) { u32 status = roothub_portstatus (ohci, i); if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC)) { changed = 1; if (i < 7) buf [0] |= 1 << (i + 1); else buf [1] |= 1 << (i - 7); continue; } /* can suspend if no ports are enabled; or if all all * enabled ports are suspended AND remote wakeup is on. */ if (!(status & RH_PS_CCS)) continue; if ((status & RH_PS_PSS) && hcd->remote_wakeup) continue; can_suspend = 0; } done: spin_unlock_irqrestore (&ohci->lock, flags); #if defined(CONFIG_PM) || defined(CONFIG_REALTEK_VENUS_USB) //cfyeh+ 2005/11/07 /* save power by suspending idle root hubs; * INTR_RD wakes us when there's work * NOTE: if we can do this, we don't need a root hub timer! */ if (can_suspend && !changed && !ohci->ed_rm_list && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) & ohci->hc_control) == OHCI_USB_OPER && time_after (jiffies, ohci->next_statechange) && usb_trylock_device (hcd->self.root_hub) ) { ohci_vdbg (ohci, "autosuspend\n"); (void) ohci_hub_suspend (hcd); hcd->state = HC_STATE_RUNNING; usb_unlock_device (hcd->self.root_hub); } #endif return changed ? length : 0; }
static int ohci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int i, changed = 0, length = 1; int can_suspend = hcd->can_wakeup; unsigned long flags; spin_lock_irqsave (&ohci->lock, flags); /* handle autosuspended root: finish resuming before * letting khubd or root hub timer see state changes. */ if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER || !HC_IS_RUNNING(hcd->state))) { can_suspend = 0; goto done; } /* undocumented erratum seen on at least rev D */ if ((ohci->flags & OHCI_QUIRK_AMD756) && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) { ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n", ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ goto done; } /* init status */ if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) buf [0] = changed = 1; else buf [0] = 0; if (ohci->num_ports > 7) { buf [1] = 0; length++; } /* look at each port */ for (i = 0; i < ohci->num_ports; i++) { u32 status = roothub_portstatus (ohci, i); if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC)) { changed = 1; if (i < 7) buf [0] |= 1 << (i + 1); else buf [1] |= 1 << (i - 7); continue; } /* can suspend if no ports are enabled; or if all all * enabled ports are suspended AND remote wakeup is on. */ if (!(status & RH_PS_CCS)) continue; if ((status & RH_PS_PSS) && hcd->remote_wakeup) continue; can_suspend = 0; } done: spin_unlock_irqrestore (&ohci->lock, flags); #ifdef CONFIG_PM /* save power by suspending idle root hubs; * INTR_RD wakes us when there's work */ if (can_suspend && !changed && !ohci->ed_rm_list && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) & ohci->hc_control) == OHCI_USB_OPER && time_after (jiffies, ohci->next_statechange) && usb_trylock_device (hcd->self.root_hub) == 0 ) { ohci_vdbg (ohci, "autosuspend\n"); (void) ohci_bus_suspend (hcd); usb_unlock_device (hcd->self.root_hub); } #endif return changed ? length : 0; }
static int ohci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ports, i, changed = 0, length = 1; int can_suspend = 1; ports = roothub_a (ohci) & RH_A_NDP; if (ports > MAX_ROOT_PORTS) { if (!HCD_IS_RUNNING(ohci->hcd.state)) return -ESHUTDOWN; ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, ohci_readl (&ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ return 0; } /* init status */ if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) buf [0] = changed = 1; else buf [0] = 0; if (ports > 7) { buf [1] = 0; length++; } /* look at each port */ for (i = 0; i < ports; i++) { u32 status = roothub_portstatus (ohci, i); if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC)) { changed = 1; if (i < 7) buf [0] |= 1 << (i + 1); else buf [1] |= 1 << (i - 7); continue; } /* can suspend if no ports are enabled; or if all all * enabled ports are suspended AND remote wakeup is on. */ if (!(status & RH_PS_CCS)) continue; if ((status & RH_PS_PSS) && ohci->hcd.remote_wakeup) continue; can_suspend = 0; } #ifdef CONFIG_PM /* save power by suspending idle root hubs; * INTR_RD wakes us when there's work */ if (can_suspend && !changed && !ohci->ed_rm_list && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) & ohci->hc_control) == OHCI_USB_OPER && down_trylock (&hcd->self.root_hub->serialize) == 0 ) { ohci_vdbg (ohci, "autosuspend\n"); (void) ohci_hub_suspend (&ohci->hcd); ohci->hcd.state = USB_STATE_RUNNING; up (&hcd->self.root_hub->serialize); } #endif return changed ? length : 0; }