static int xhci_run_finished(struct xhci_hcd *xhci)
{
+ struct xhci_interrupter *ir = xhci->interrupter;
unsigned long flags;
u32 temp;
writel(temp, &xhci->op_regs->command);
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Enable primary interrupter");
- temp = readl(&xhci->ir_set->irq_pending);
- writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending);
+ temp = readl(&ir->ir_set->irq_pending);
+ writel(ER_IRQ_ENABLE(temp), &ir->ir_set->irq_pending);
if (xhci_start(xhci)) {
xhci_halt(xhci);
u64 temp_64;
int ret;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-
+ struct xhci_interrupter *ir = xhci->interrupter;
/* Start the xHCI host controller running only after the USB 2.0 roothub
* is setup.
*/
if (ret)
return ret;
- temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+ temp_64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
temp_64 &= ~ERST_PTR_MASK;
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"ERST deq = 64'h%0lx", (long unsigned int) temp_64);
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Set the interrupt modulation register");
- temp = readl(&xhci->ir_set->irq_control);
+ temp = readl(&ir->ir_set->irq_control);
temp &= ~ER_IRQ_INTERVAL_MASK;
temp |= (xhci->imod_interval / 250) & ER_IRQ_INTERVAL_MASK;
- writel(temp, &xhci->ir_set->irq_control);
+ writel(temp, &ir->ir_set->irq_control);
if (xhci->quirks & XHCI_NEC_HOST) {
struct xhci_command *command;
"// Disabling event ring interrupts");
temp = readl(&xhci->op_regs->status);
writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status);
- temp = readl(&xhci->ir_set->irq_pending);
- writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
+ temp = readl(&xhci->interrupter->ir_set->irq_pending);
+ writel(ER_IRQ_DISABLE(temp), &xhci->interrupter->ir_set->irq_pending);
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "cleaning up memory");
xhci_mem_cleanup(xhci);
#ifdef CONFIG_PM
static void xhci_save_registers(struct xhci_hcd *xhci)
{
+ struct xhci_interrupter *ir = xhci->interrupter;
+
xhci->s3.command = readl(&xhci->op_regs->command);
xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification);
xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
xhci->s3.config_reg = readl(&xhci->op_regs->config_reg);
- xhci->s3.erst_size = readl(&xhci->ir_set->erst_size);
- xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
- xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
- xhci->s3.irq_pending = readl(&xhci->ir_set->irq_pending);
- xhci->s3.irq_control = readl(&xhci->ir_set->irq_control);
+
+ if (!ir)
+ return;
+
+ ir->s3_erst_size = readl(&ir->ir_set->erst_size);
+ ir->s3_erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base);
+ ir->s3_erst_dequeue = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
+ ir->s3_irq_pending = readl(&ir->ir_set->irq_pending);
+ ir->s3_irq_control = readl(&ir->ir_set->irq_control);
}
static void xhci_restore_registers(struct xhci_hcd *xhci)
{
+ struct xhci_interrupter *ir = xhci->interrupter;
+
writel(xhci->s3.command, &xhci->op_regs->command);
writel(xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
writel(xhci->s3.config_reg, &xhci->op_regs->config_reg);
- writel(xhci->s3.erst_size, &xhci->ir_set->erst_size);
- xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
- xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
- writel(xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
- writel(xhci->s3.irq_control, &xhci->ir_set->irq_control);
+ writel(ir->s3_erst_size, &ir->ir_set->erst_size);
+ xhci_write_64(xhci, ir->s3_erst_base, &ir->ir_set->erst_base);
+ xhci_write_64(xhci, ir->s3_erst_dequeue, &ir->ir_set->erst_dequeue);
+ writel(ir->s3_irq_pending, &ir->ir_set->irq_pending);
+ writel(ir->s3_irq_control, &ir->ir_set->irq_control);
}
static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
xhci_dbg(xhci, "// Disabling event ring interrupts\n");
temp = readl(&xhci->op_regs->status);
writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status);
- temp = readl(&xhci->ir_set->irq_pending);
- writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
+ temp = readl(&xhci->interrupter->ir_set->irq_pending);
+ writel(ER_IRQ_DISABLE(temp), &xhci->interrupter->ir_set->irq_pending);
xhci_dbg(xhci, "cleaning up memory\n");
xhci_mem_cleanup(xhci);
if (xhci->hci_version > 0x100)
xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
+ /* xhci-plat or xhci-pci might have set max_interrupters already */
+ if ((!xhci->max_interrupters) ||
+ xhci->max_interrupters > HCS_MAX_INTRS(xhci->hcs_params1))
+ xhci->max_interrupters = HCS_MAX_INTRS(xhci->hcs_params1);
+
xhci->quirks |= quirks;
get_quirks(dev, xhci);