[U-Boot] [PATCH] usb: dwc2: fix gadget disconnect

Lukasz Majewski lukma at denx.de
Fri Apr 19 06:30:47 UTC 2019


On Wed, 17 Apr 2019 16:46:13 +0200
Fabrice Gasnier <fabrice.gasnier at st.com> 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>
> ---
> 
>  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(&reg->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, &reg->gotgint);
>  	}
>  
>  	if (intr_status & INT_RESUME) {

Acked-by: Lukasz Majewski <lukma at denx.de>

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: <http://lists.denx.de/pipermail/u-boot/attachments/20190419/3d53fe64/attachment.sig>


More information about the U-Boot mailing list