> From: dinguyen@xxxxxxxxxx [mailto:dinguyen@xxxxxxxxxx] > Sent: Monday, February 03, 2014 9:00 AM Hi Dinh, > According to the spec for the DWC2 controller, when the PRTINT interrupt fires, > the application must clear the appropriate status bit in the Host Port Control > and Status register to clear this bit. > > When disconnecting an A-cable when the dwc2 host driver, the PRTINT fires, but > only the GINTSTS_PRTINT status is cleared, no action is done with the HPRT0 > register. The HPRT0_ENACHG bit in the HPRT0 must also be poked to correctly > clear the GINTSTS_PRTINT interrupt. > > I am seeing this behavoir on v2.93 of the DWC2 IP. When I disconnect an OTG > A-cable adapter, the PRTINT interrupt fires when the DWC2 is in device mode > and is never cleared. > > This patch adds the function to read the HPRT0 register when the PRTINT fires > and the dwc2 IP has already transitioned to device mode. This function is only > clearing the HPRT0_ENACHG bit for now, but can be modified to handle more. > > Signed-off-by: Dinh Nguyen <dinguyen@xxxxxxxxxx> > Cc: Paul Zimmerman <paulz@xxxxxxxxxxxx> > Cc: Matt Porter <mporter@xxxxxxxxxx> > Cc: Matthijs Kooijman <matthijs@xxxxxxxx> > --- > drivers/usb/dwc2/core_intr.c | 20 ++++++++++++++++++++ > 1 file changed, 20 insertions(+) > > diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c > index 12dde73..64fee902 100644 > --- a/drivers/usb/dwc2/core_intr.c > +++ b/drivers/usb/dwc2/core_intr.c > @@ -76,6 +76,24 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg) > } > > /** > + * dwc2_handle_usb_port_intr - handles OTG PRTINT interrupts. > + * When the PRTINT interrupt fires, there are certain status bits in the Host > + * Port that needs to get cleared. > + * > + * @hsotg: Programming view of DWC_otg controller > + */ > +static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg) > +{ > + u32 hprt0; > + > + hprt0 = readl(hsotg->regs + HPRT0); > + if (hprt0 & HPRT0_ENACHG) { This would be a little cleaner like this: u32 hprt0 = readl(hsotg->regs + HPRT0); if (hprt0 & HPRT0_ENACHG) { > + hprt0 |= HPRT0_ENACHG; > + writel(hprt0, hsotg->regs + HPRT0); > + } > +} > + > +/** > * dwc2_handle_mode_mismatch_intr() - Logs a mode mismatch warning message > * > * @hsotg: Programming view of DWC_otg controller > @@ -583,8 +601,10 @@ irq_retry: > if (dwc2_is_device_mode(hsotg)) { > dev_dbg(hsotg->dev, > " --Port interrupt received in Device mode--\n"); > + dwc2_handle_usb_port_intr(hsotg); > gintsts = GINTSTS_PRTINT; > writel(gintsts, hsotg->regs + GINTSTS); > + dwc2_handle_usb_port_intr(hsotg); Why do you have two calls to dwc2_handle_usb_port_intr() here? Does it still work if you remove the first call? I don't see this problem on our internal FPGA platform, so I will just have to take your word that this fixes a problem. If you resubmit the patch with just a single call to dwc2_handle_usb_port_intr(), I will ack it. -- Paul -- 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