On 10/28/2016 04:56 AM, David Lechner wrote: > On 10/26/2016 05:58 AM, Alexandre Bailon wrote: >> When the phy is forced in host mode, only the first hot plug and >> hot remove works. That is actually because the driver execute the >> OTG workaround, whereas it is not applicable in host or device mode. >> Indeed, to work correctly, the VBUS sense and session end comparator >> must be enabled, what is only possible when the phy is in OTG mode. >> Only execute the workaround if the phy is in OTG mode. >> >> Signed-off-by: Alexandre Bailon <abailon@xxxxxxxxxxxx> >> --- >> drivers/usb/musb/da8xx.c | 11 +++++++++++ >> 1 file changed, 11 insertions(+) >> >> diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c >> index 6749aa1..b8a6b65 100644 >> --- a/drivers/usb/musb/da8xx.c >> +++ b/drivers/usb/musb/da8xx.c >> @@ -145,6 +145,17 @@ static void otg_timer(unsigned long _musb) >> unsigned long flags; >> >> /* >> + * We should only execute the OTG workaround when the phy is in OTG >> + * mode. The workaround require the VBUS sense and the session end >> + * comparator to be enabled, what is only possible if the phy is in >> + * OTG mode. As the workaround is only required to detect if the >> + * controller must act as host or device, we can safely exit OTG is >> + * not in use. >> + */ >> + if (musb->port_mode != MUSB_PORT_MODE_DUAL_ROLE) > > musb->port_mode is not valid if we have changed the mode via sysfs. It > only reflects the mode set during driver probe. > > Furthermore, this breaks the host mode completely for me. The first hot > plug is not even detected. > >> + return; >> + >> + /* >> * We poll because DaVinci's won't expose several OTG-critical >> * status change events (from the transceiver) otherwise. >> */ >> > > > The way this is working for me (on AM1808) is this: > > The problem is not that the OTG workaround is being used. The problem is > that after disconnect, the VBUSDRV is turned off. If you look at the > handler for DA8XX_INTR_DRVVBUS in da8xx_musb_interrupt(), you will see > that if VBUSDRV is off, then drvvbus == 0, which puts the musb state > back to device mode. > > I also ran into a similar problem a while back[1] that if you use a > self-powered device in host mode, it immediately becomes disconnected. > This is for the exact same reason. When a port detects a self-powered > device, it turns of VBUSDRV, which triggers the DA8XX_INTR_DRVVBUS > interrupt. As we have seen above, this takes the port out of host mode. > > The workaround that I have found that seems to fix both cases is to add > and else if statement that toggles the PHY host override when we are > forcing host mode and the VBUSDRV is turned off. I like this workaround. > > Here is a partial diff of drivers/usb/musb/da8xx.c to show what I mean: > > @@ -304,10 +309,14 @@ static irqreturn_t da8xx_musb_interrupt(int irq, > void *hci) > * Also, DRVVBUS pulses for SRP (but not at 5 V)... > */ > if (status & (DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT)) { > + struct da8xx_glue *glue = > + dev_get_drvdata(musb->controller->parent); > int drvvbus = musb_readl(reg_base, DA8XX_USB_STAT_REG); > void __iomem *mregs = musb->mregs; > u8 devctl = musb_readb(mregs, MUSB_DEVCTL); > - int err; > + int cfgchip2, err; > + > + regmap_read(glue->cfgchip, CFGCHIP(2), &cfgchip2); > > err = musb->int_usb & MUSB_INTR_VBUSERROR; > if (err) { > @@ -332,10 +341,25 @@ static irqreturn_t da8xx_musb_interrupt(int irq, > void *hci) > musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; > portstate(musb->port1_status |= > USB_PORT_STAT_POWER); > del_timer(&otg_workaround); > + } else if ((cfgchip2 & CFGCHIP2_OTGMODE_MASK) > + == CFGCHIP2_OTGMODE_FORCE_HOST) { > + /* > + * If we are forcing host mode, VBUSDRV is > turned off > + * after a device is disconnected. We need to > toggle the > + * VBUS/ID override to trigger turn it back on, > which > + * has the effect of triggering > DA8XX_INTR_DRVVBUS again. > + */ > + regmap_write_bits(glue->cfgchip, CFGCHIP(2), > + CFGCHIP2_OTGMODE_MASK, > + CFGCHIP2_OTGMODE_NO_OVERRIDE); > + regmap_write_bits(glue->cfgchip, CFGCHIP(2), > + CFGCHIP2_OTGMODE_MASK, > + CFGCHIP2_OTGMODE_FORCE_HOST); > } else { > musb->is_active = 0; > MUSB_DEV_MODE(musb); > I haven't thought to this workaround. Actually, my goal with this patch was to prevent VBUSDRV to be turned off. When I hit the issues, I captured some traces and these traces let think VBUSDRV is turned off when the OTG workaround clear the bit MUSB_DEVCTL_SESSION. -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html