static void xhci_port_set_test_mode(struct xhci_hcd *xhci, u16 test_mode, u16 wIndex) { u32 temp; __le32 __iomem *addr; /* xhci only supports test mode for usb2 ports, i.e. xhci->main_hcd */ addr = xhci_get_port_io_addr(xhci->main_hcd, wIndex); temp = readl(addr + PORTPMSC); temp |= test_mode << PORT_TEST_MODE_SHIFT; writel(temp, addr + PORTPMSC); xhci->test_mode = test_mode; if (test_mode == TEST_FORCE_EN) xhci_start(xhci); }
static int xhci_run_finished(struct xhci_hcd *xhci) { if (xhci_start(xhci)) { xhci_halt(xhci); return -ENODEV; } xhci->shared_hcd->state = HC_STATE_RUNNING; xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; if (xhci->quirks & XHCI_NEC_HOST) xhci_ring_cmd_db(xhci); xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_run for USB3 roothub"); return 0; }
int xhci_bus_resume(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); int max_ports, port_index; __le32 __iomem **port_array; struct xhci_bus_state *bus_state; u32 temp; unsigned long flags; max_ports = xhci_get_ports(hcd, &port_array); bus_state = &xhci->bus_state[hcd_index(hcd)]; if (time_before_eq(jiffies, bus_state->next_statechange)) usleep_range(10000, 11000); spin_lock_irqsave(&xhci->lock, flags); if (!HCD_HW_ACCESSIBLE(hcd)) { spin_unlock_irqrestore(&xhci->lock, flags); return -ESHUTDOWN; } /* delay the irqs */ temp = xhci_readl(xhci, &xhci->op_regs->command); temp &= ~CMD_EIE; xhci_writel(xhci, temp, &xhci->op_regs->command); if ((xhci->quirks & XHCI_RESET_RS_ON_RESUME_QUIRK) && HC_IS_SUSPENDED(xhci->main_hcd->state) && HC_IS_SUSPENDED(xhci->shared_hcd->state)) { xhci_halt(xhci); if (!xhci_start(xhci)) xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; } port_index = max_ports; while (port_index--) { /* Check whether need resume ports. If needed resume port and disable remote wakeup */ u32 temp; int slot_id; temp = xhci_readl(xhci, port_array[port_index]); if (DEV_SUPERSPEED(temp)) temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); else temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); if (test_bit(port_index, &bus_state->bus_suspended) && (temp & PORT_PLS_MASK)) { if (DEV_SUPERSPEED(temp)) { xhci_set_link_state(xhci, port_array, port_index, XDEV_U0); } else { xhci_set_link_state(xhci, port_array, port_index, XDEV_RESUME); spin_unlock_irqrestore(&xhci->lock, flags); usleep_range(20000, 21000); spin_lock_irqsave(&xhci->lock, flags); xhci_set_link_state(xhci, port_array, port_index, XDEV_U0); } /* wait for the port to enter U0 and report port link * state change. */ spin_unlock_irqrestore(&xhci->lock, flags); usleep_range(20000, 21000); spin_lock_irqsave(&xhci->lock, flags); /* Clear PLC */ xhci_test_and_clear_bit(xhci, port_array, port_index, PORT_PLC); slot_id = xhci_find_slot_id_by_port(hcd, xhci, port_index + 1); if (slot_id) xhci_ring_device(xhci, slot_id); } else { xhci_writel(xhci, temp, port_array[port_index]); if (xhci->quirks & XHCI_PORTSC_DELAY) ndelay(100); } if (hcd->speed != HCD_USB3) { /* disable remote wake up for USB 2.0 */ __le32 __iomem *addr; u32 tmp; /* Add one to the port status register address to get * the port power control register address. */ addr = port_array[port_index] + 1; tmp = xhci_readl(xhci, addr); tmp &= ~PORT_RWE; xhci_writel(xhci, tmp, addr); if (xhci->quirks & XHCI_PORTSC_DELAY) ndelay(100); } } (void) xhci_readl(xhci, &xhci->op_regs->command); bus_state->next_statechange = jiffies + msecs_to_jiffies(5); /* re-enable irqs */ temp = xhci_readl(xhci, &xhci->op_regs->command); temp |= CMD_EIE; xhci_writel(xhci, temp, &xhci->op_regs->command); temp = xhci_readl(xhci, &xhci->op_regs->command); spin_unlock_irqrestore(&xhci->lock, flags); return 0; }
static void xhci_reinit (hci_t *controller) { xhci_t *const xhci = XHCI_INST(controller); if (xhci_wait_ready(xhci)) return; /* Enable all available slots */ xhci->opreg->config = xhci->max_slots_en; /* Set DCBAA */ xhci->opreg->dcbaap_lo = virt_to_phys(xhci->dcbaa); xhci->opreg->dcbaap_hi = 0; /* Initialize command ring */ xhci_init_cycle_ring(&xhci->cr, COMMAND_RING_SIZE); xhci_debug("command ring @%p (0x%08x)\n", xhci->cr.ring, virt_to_phys(xhci->cr.ring)); xhci->opreg->crcr_lo = virt_to_phys(xhci->cr.ring) | CRCR_RCS; xhci->opreg->crcr_hi = 0; /* Make sure interrupts are disabled */ xhci->opreg->usbcmd &= ~USBCMD_INTE; /* Initialize event ring */ xhci_reset_event_ring(&xhci->er); xhci_debug("event ring @%p (0x%08x)\n", xhci->er.ring, virt_to_phys(xhci->er.ring)); xhci_debug("ERST Max: 0x%lx -> 0x%lx entries\n", xhci->capreg->ERST_Max, 1 << xhci->capreg->ERST_Max); memset((void*)xhci->ev_ring_table, 0x00, sizeof(erst_entry_t)); xhci->ev_ring_table[0].seg_base_lo = virt_to_phys(xhci->er.ring); xhci->ev_ring_table[0].seg_base_hi = 0; xhci->ev_ring_table[0].seg_size = EVENT_RING_SIZE; /* Initialize primary interrupter */ xhci->hcrreg->intrrs[0].erstsz = 1; xhci_update_event_dq(xhci); /* erstba has to be written at last */ xhci->hcrreg->intrrs[0].erstba_lo = virt_to_phys(xhci->ev_ring_table); xhci->hcrreg->intrrs[0].erstba_hi = 0; xhci_start(controller); #ifdef USB_DEBUG int i; for (i = 0; i < 32; ++i) { xhci_debug("NOOP run #%d\n", i); trb_t *const cmd = xhci_next_command_trb(xhci); TRB_SET(TT, cmd, TRB_CMD_NOOP); xhci_post_command(xhci); /* Wait for result in event ring */ xhci_wait_for_command_done(xhci, cmd, 1); xhci_debug("Command ring is %srunning\n", (xhci->opreg->crcr_lo & CRCR_CRR) ? "" : "not "); } #endif }