usb: gadget: dwc2_udc_otg: implement pullup()

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:
* when pullup is on, clear SOFT_DISCONNECT
* when pullup is off, set SOFT_DISCONNECT

This is especially useful when a gadget disconnection is initiated but
no board_usb_cleanup() is called.

Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index 77988f7..2bf7ed8 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -236,6 +236,14 @@
 	return 0;
 }
 
+static int dwc2_gadget_pullup(struct usb_gadget *g, int is_on)
+{
+	clrsetbits_le32(&reg->dctl, SOFT_DISCONNECT,
+			is_on ? 0 : SOFT_DISCONNECT);
+
+	return 0;
+}
+
 #if !CONFIG_IS_ENABLED(DM_USB_GADGET)
 /*
   Register entry point for the peripheral controller driver.
@@ -805,6 +813,7 @@
 }
 
 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,