On Wed, 17 Apr 2019 16:46:13 +0200
Fabrice Gasnier <fabrice.gasn...@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.gasn...@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 <lu...@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: lu...@denx.de

Attachment: pgpaRVqBOUbcK.pgp
Description: OpenPGP digital signature

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to