From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lukasz Majewski Date: Fri, 19 Apr 2019 08:30:47 +0200 Subject: [U-Boot] [PATCH] usb: dwc2: fix gadget disconnect In-Reply-To: <1555512373-10142-1-git-send-email-fabrice.gasnier@st.com> References: <1555512373-10142-1-git-send-email-fabrice.gasnier@st.com> Message-ID: <20190419083047.54e00347@jawa> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On Wed, 17 Apr 2019 16:46:13 +0200 Fabrice Gasnier wrote: > This fixes a disconnect issue detected with fastboot command, when > using dwc2 driver. > - On u-boot side: > uboot>$ fastboot 0 > - On USB host PC side, few seconds after > PC>$ fastboot reboot # Get stuck, uboot target never reboots > > By enabling DEBUG_ISR logs, the bus suspend interrupt is seen before > the PC command has been issued. When the USB bus suspend occurs, > there's a HACK that disables the fastboot (composite driver). Here is > the call stack upon USB bus suspend: > - dwc2_handle_usb_suspend_intr() > - dev->driver->disconnect() > - composite_disconnect() > - reset_config() > - f->disable() > - fastboot_disable() > - usb_ep_disable(f_fb->out_ep); > - usb_ep_disable(f_fb->in_ep); > .. other disable calls. > > When the resume interrupt happens, everything has been disabled, then > nothing happens. fastboot command gets stuck on HOST side. > > Remove original HACK, that disconnects the composite driver upon > USB bus suspend. Implement disconnect detection instead: > - check GINTSTS OTG interrupt > - read GOTGINT register > - check GOTGINT, SesEndDet bit (e.g. session end) > This is inspired by what is implemented currently in Linux dwc2 > driver. > > Signed-off-by: Fabrice Gasnier > --- > > drivers/usb/gadget/dwc2_udc_otg_regs.h | 6 +++++- > drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c | 14 ++++++++++++-- > 2 files changed, 17 insertions(+), 3 deletions(-) > > diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h > b/drivers/usb/gadget/dwc2_udc_otg_regs.h index a1829b3..b685256 100644 > --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h > +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h > @@ -86,6 +86,9 @@ struct dwc2_usbotg_reg { > #define B_SESSION_VALID (0x1<<19) > #define A_SESSION_VALID (0x1<<18) > > +/* DWC2_UDC_OTG_GOTINT */ > +#define GOTGINT_SES_END_DET (1<<2) > + > /* DWC2_UDC_OTG_GAHBCFG */ > #define PTXFE_HALF (0<<8) > #define PTXFE_ZERO (1<<8) > @@ -118,6 +121,7 @@ struct dwc2_usbotg_reg { > #define INT_NP_TX_FIFO_EMPTY (0x1<<5) > #define INT_RX_FIFO_NOT_EMPTY (0x1<<4) > #define INT_SOF (0x1<<3) > +#define INT_OTG (0x1<<2) > #define INT_DEV_MODE (0x0<<0) > #define INT_HOST_MODE (0x1<<1) > #define INT_GOUTNakEff (0x01<<7) > @@ -246,7 +250,7 @@ struct dwc2_usbotg_reg { > > /* Masks definitions */ > #define GINTMSK_INIT (INT_OUT_EP | INT_IN_EP | INT_RESUME | > INT_ENUMDONE\ > - | INT_RESET | INT_SUSPEND) > + | INT_RESET | INT_SUSPEND | INT_OTG) > #define DOEPMSK_INIT (CTRL_OUT_EP_SETUP_PHASE_DONE | > AHB_ERROR|TRANSFER_DONE) #define DIEPMSK_INIT > (NON_ISO_IN_EP_TIMEOUT|AHB_ERROR|TRANSFER_DONE) #define > GAHBCFG_INIT (PTXFE_HALF | NPTXFE_HALF | MODE_DMA | > BURST_INCR4\ diff --git a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c > b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c index a75af49..7eb632d > 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c +++ > b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c @@ -467,7 +467,7 @@ > static void process_ep_out_intr(struct dwc2_udc *dev) static int > dwc2_udc_irq(int irq, void *_dev) { > struct dwc2_udc *dev = _dev; > - u32 intr_status; > + u32 intr_status, gotgint; > u32 usb_status, gintmsk; > unsigned long flags = 0; > > @@ -521,14 +521,24 @@ static int dwc2_udc_irq(int irq, void *_dev) > && dev->driver) { > if (dev->driver->suspend) > dev->driver->suspend(&dev->gadget); > + } > + } > + > + if (intr_status & INT_OTG) { > + gotgint = readl(®->gotgint); > + debug_cond(DEBUG_ISR, > + "\tOTG interrupt: (GOTGINT):0x%x\n", > gotgint); > - /* HACK to let gadget detect disconnected > state */ > + if (gotgint & GOTGINT_SES_END_DET) { > + debug_cond(DEBUG_ISR, "\t\tSession End > Detected\n"); > + /* Let gadget detect disconnected state */ > if (dev->driver->disconnect) { > spin_unlock_irqrestore(&dev->lock, > flags); dev->driver->disconnect(&dev->gadget); > spin_lock_irqsave(&dev->lock, flags); > } > } > + writel(gotgint, ®->gotgint); > } > > if (intr_status & INT_RESUME) { Acked-by: Lukasz Majewski Best regards, Lukasz Majewski -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 488 bytes Desc: OpenPGP digital signature URL: