[U-Boot] [PATCH] usb: dwc2: fix gadget disconnect
Marek Vasut
marex at denx.de
Wed Apr 17 18:54:58 UTC 2019
On 4/17/19 4:46 PM, 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 <fabrice.gasnier at st.com>
Reviewed-by: Marek Vasut <marex at denx.de>
This is Lukasz's topic, so you need his RB too.
Thanks
> ---
>
> 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) {
>
--
Best regards,
Marek Vasut
More information about the U-Boot
mailing list