[PATCH] usb: gadget: dwc2_udc_otg: implement pullup()

Harald Seiler hws at denx.de
Tue Jan 10 14:30:14 CET 2023


Hi,

On Tue, 2023-01-10 at 10:11 +0100, Mattijs Korpershoek wrote:
> Pullup is used by the usb framework in order to do software-controlled
> usb_gadget_connect() and usb_gadget_disconnect().
> 
> Implement pullup() for dwc2 using the SOFT_DISCONNECT bit in the dctl
> register.
> 
> This is especially useful when a gadget disconnection is initiated but
> no board_usb_cleanup() is called.
> 
> Signed-off-by: Mattijs Korpershoek <mkorpershoek at baylibre.com>
> ---
> On some boards using the dwc2 controller, like the Khadas VIM3L, whenever
> usb_gadget_release() is called, the D+ and D- lines are in an unknown state.
> 
> Because of that, the host can't detect usb disconnection.
> 
> It was attempted to be be fixed with [1] but ended up doing the gadget disconnection
> too early, creating issues on NXP-based boards which use uuu [2].
> 
> By implementing pullup() in the controller driver, we ensure that the disconnection will
> only be done when the framework calls usb_gadget_disconnect().
> 
> [1] https://lore.kernel.org/all/20220728-reset-usb-controller-v2-1-ef7657ce78b1@baylibre.com/
> [2] https://lore.kernel.org/all/20230107164807.3597020-1-dario.binacchi@amarulasolutions.com/
> ---
>  drivers/usb/gadget/dwc2_udc_otg.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
> index 77988f78ab30..93ed9712d18a 100644
> --- a/drivers/usb/gadget/dwc2_udc_otg.c
> +++ b/drivers/usb/gadget/dwc2_udc_otg.c
> @@ -236,6 +236,21 @@ static int udc_enable(struct dwc2_udc *dev)
>  	return 0;
>  }
>  
> +static int dwc2_gadget_pullup(struct usb_gadget *g, int is_on)
> +{
> +	unsigned int uTemp;

Just some minor points about style...

I think the `u32` type should be used for 32-bit registers instead.
More explicit and no room for accidentally choosing the wrong size.

Also, U-Boot and Linux don't use hungarian notation for variable names,
just call it `tmp` or even better `dctl` to be explicit.

> +
> +	is_on = !!is_on;

This is superfluous, the if condition works either way.

> +	uTemp = readl(&reg->dctl);
> +	if (is_on)
> +		uTemp = uTemp & ~SOFT_DISCONNECT;
> +	else
> +		uTemp |= SOFT_DISCONNECT;
> +	writel(uTemp, &reg->dctl);
> +
> +	return 0;
> +}
> +
>  #if !CONFIG_IS_ENABLED(DM_USB_GADGET)
>  /*
>    Register entry point for the peripheral controller driver.
> @@ -805,6 +820,7 @@ static void dwc2_fifo_flush(struct usb_ep *_ep)
>  }
>  
>  static const struct usb_gadget_ops dwc2_udc_ops = {
> +	.pullup = dwc2_gadget_pullup,
>  	/* current versions must always be self-powered */
>  #if CONFIG_IS_ENABLED(DM_USB_GADGET)
>  	.udc_start		= dwc2_gadget_start,
> 
> ---
> base-commit: 7b84c973b96775576dcff228d865e8570be26c82
> change-id: 20230110-dwc2-pullup-5b0f5a073d6b
> 
> Best regards,

Regards,

Harald


More information about the U-Boot mailing list