* The Mentor core doesn't debounce VBUS as needed
* to cope with device connect current spikes. This
* means it's not uncommon for bus-powered devices
* to get VBUS errors during enumeration.
*
* This is a workaround, but newer RTL from Mentor
* seems to allow a better one: "re"-starting sessions
* without waiting for VBUS to stop registering in
* devctl.
*/
musb->int_usb &= ~MUSB_INTR_VBUSERROR;
musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
mod_timer(&musb->otg_workaround,
jiffies + POLL_SECONDS * HZ);
WARNING("VBUS error workaround (delay coming)\n"); 这句话会一直打印,目前猜测的是硬件的电压不太稳定,所以才会一直打印。
} else if (is_host_enabled(musb) && drvvbus) {
if ((devctl & MUSB_DEVCTL_SESSION) &&
!(devctl & MUSB_DEVCTL_BDEVICE) &&
!(devctl & MUSB_DEVCTL_HM)) {
dev_dbg(musb->controller,
"Only micro-A plug is connected\n");
} else {
if (musb->is_active)
del_timer(&musb->otg_workaround);
else
musb->is_active = 1;
MUSB_HST_MODE(musb);
musb->xceiv->default_a = 1;
musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
}
} else {
musb->is_active = 0;
MUSB_DEV_MODE(musb);
musb->xceiv->default_a = 0;
musb->xceiv->state = OTG_STATE_B_IDLE;
}
/* NOTE: this must complete power-on within 100 ms. */
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
otg_state_string(musb->xceiv->state),
err ? " ERROR" : "",
devctl);
ret = IRQ_HANDLED;
}
if (musb->int_tx || musb->int_rx || musb->int_usb)
ret |= musb_interrupt(musb);
eoi:
/* EOI needs to be written for the IRQ to be re-asserted. */
if (ret == IRQ_HANDLED || epintr || usbintr) {
/* write EOI */
musb_writel(reg_base, USB_IRQ_EOI, 1);
}
/* Poll for ID change */
if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
mod_timer(&musb->otg_workaround, jiffies + POLL_SECONDS * HZ);
spin_unlock_irqrestore(&musb->lock, flags);
if (ret != IRQ_HANDLED) {
if (epintr || usbintr)
/*
* We sometimes get unhandled IRQs in the peripheral
* mode from EP0 and SOF...
*/
dev_dbg(musb->controller, "Unhandled USB IRQ %08x-%08x\n",
epintr, usbintr);
else if (printk_ratelimit())
/*
* We've seen series of spurious interrupts in the
* peripheral mode after USB reset and then after some
* time a real interrupt storm starting...
*/
dev_dbg(musb->controller, "Spurious IRQ, CPPI 4.1 status %08x, %08x\n",
pend1, pend2);
}
if (is_babble) {
if (musb->enable_babble_work)
schedule_work(&musb->work);
else {
musb_writeb(musb->mregs, MUSB_DEVCTL,
musb_readb(musb->mregs, MUSB_DEVCTL) |
MUSB_DEVCTL_SESSION);
}
}
return ret;
}
