Try to recover from vbus errors. Some devices draw too much

current at plug time, causing a trancient error.
This commit is contained in:
bouyer 2014-07-17 19:58:18 +00:00
parent 598514d2bc
commit ecf710daf3
3 changed files with 45 additions and 18 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: tiotg.c,v 1.1 2014/07/16 18:27:19 bouyer Exp $ */
/* $NetBSD: tiotg.c,v 1.2 2014/07/17 19:58:18 bouyer Exp $ */
/*
* Copyright (c) 2013 Manuel Bouyer. All rights reserved.
*
@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tiotg.c,v 1.1 2014/07/16 18:27:19 bouyer Exp $");
__KERNEL_RCSID(0, "$NetBSD: tiotg.c,v 1.2 2014/07/17 19:58:18 bouyer Exp $");
#include "opt_omap.h"
#include "locators.h"
@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: tiotg.c,v 1.1 2014/07/16 18:27:19 bouyer Exp $");
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usb_mem.h>
#include <dev/usb/motgreg.h>
#include <dev/usb/motgvar.h>
#define MOTG_DEBUG
@ -376,27 +377,42 @@ ti_motg_intr(void *v)
{
struct ti_motg_softc *sc = v;
uint32_t stat, stat0, stat1;
int vbus = 0;
int rv = 0;
int i;
mutex_spin_enter(&sc->sc_motg.sc_intr_lock);
stat = TIOTG_USBC_READ4(sc, USBCTRL_STAT);
stat0 = TIOTG_USBC_READ4(sc, USBCTRL_IRQ_STAT0);
stat1 = TIOTG_USBC_READ4(sc, USBCTRL_IRQ_STAT1);
DPRINTF(("USB %d 0x%x 0x%x stat %d\n", sc->sc_ctrlport, stat0, stat1, stat));
DPRINTF(("USB %d 0x%x 0x%x stat %d\n",
sc->sc_ctrlport, stat0, stat1, stat));
/* try to deal with vbus errors */
if (stat1 & MUSB2_MASK_IVBUSERR ) {
stat1 &= ~MUSB2_MASK_IVBUSERR;
for (i = 0; i < 1000; i++) {
TIOTG_USBC_WRITE4(sc, USBCTRL_IRQ_STAT1,
MUSB2_MASK_IVBUSERR);
motg_intr_vbus(&sc->sc_motg, stat & 0x1);
delay(1000);
stat = TIOTG_USBC_READ4(sc, USBCTRL_STAT);
if (stat & 0x1)
break;
}
}
if (stat0) {
TIOTG_USBC_WRITE4(sc, USBCTRL_IRQ_STAT0, stat0);
}
if (stat1) {
TIOTG_USBC_WRITE4(sc, USBCTRL_IRQ_STAT1, stat1);
}
if (stat1 & USBCTRL_IRQ_STAT1_DRVVBUS) {
vbus = ((stat & 0x1) ? 1 : 0);
DPRINTF(("USB %d stat %d\n", sc->sc_ctrlport, stat));
if ((stat & 0x1) == 0) {
mutex_spin_exit(&sc->sc_motg.sc_intr_lock);
aprint_error_dev(sc->sc_motg.sc_dev, ": vbus error\n");
return 1;
}
if (stat0 != 0 || stat1 != 0 || stat != 0) {
if (stat0 != 0 || stat1 != 0) {
rv = motg_intr(&sc->sc_motg, ((stat0 >> 16) & 0xffff),
stat0 & 0xffff, stat1 & 0xff, vbus);
stat0 & 0xffff, stat1 & 0xff);
}
mutex_spin_exit(&sc->sc_motg.sc_intr_lock);
return rv;

View File

@ -1,4 +1,4 @@
/* $NetBSD: motg.c,v 1.1 2014/07/16 18:22:23 bouyer Exp $ */
/* $NetBSD: motg.c,v 1.2 2014/07/17 19:58:18 bouyer Exp $ */
/*
* Copyright (c) 1998, 2004, 2011, 2012, 2014 The NetBSD Foundation, Inc.
@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.1 2014/07/16 18:22:23 bouyer Exp $");
__KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.2 2014/07/17 19:58:18 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -464,10 +464,6 @@ motg_open(usbd_pipe_handle pipe)
struct motg_softc *sc = pipe->device->bus->hci_private;
struct motg_pipe *otgpipe = (struct motg_pipe *)pipe;
usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
#if 0
usbd_status err = USBD_NOMEM;
int ival;
#endif
DPRINTF(("motg_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
pipe, pipe->device->address,
@ -660,7 +656,7 @@ motg_poll(struct usbd_bus *bus)
int
motg_intr(struct motg_softc *sc, uint16_t rx_ep, uint16_t tx_ep,
uint8_t ctrl, int vbus)
uint8_t ctrl)
{
KASSERT(mutex_owned(&sc->sc_intr_lock));
sc->sc_intr_tx_ep = tx_ep;
@ -674,6 +670,20 @@ motg_intr(struct motg_softc *sc, uint16_t rx_ep, uint16_t tx_ep,
return 1;
}
int
motg_intr_vbus(struct motg_softc *sc, int vbus)
{
uint8_t val;
if (sc->sc_mode == MOTG_MODE_HOST && vbus == 0) {
DPRINTF(("motg_intr_vbus: vbus down, try to re-enable\n"));
/* try to re-enter session for Host mode */
val = UREAD1(sc, MUSB2_REG_DEVCTL);
val |= MUSB2_MASK_SESS;
UWRITE1(sc, MUSB2_REG_DEVCTL, val);
}
return 1;
}
usbd_status
motg_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: motgvar.h,v 1.1 2014/07/16 18:22:23 bouyer Exp $ */
/* $NetBSD: motgvar.h,v 1.2 2014/07/17 19:58:18 bouyer Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -121,7 +121,8 @@ struct motg_xfer {
usbd_status motg_init(struct motg_softc *);
int motg_intr(struct motg_softc *, uint16_t, uint16_t, uint8_t, int);
int motg_intr(struct motg_softc *, uint16_t, uint16_t, uint8_t);
int motg_intr_vbus(struct motg_softc *, int);
int motg_detach(struct motg_softc *, int);
void motg_childdet(device_t, device_t);
int motg_activate(device_t, enum devact);