usb: dwc2: add support for STM32MP1

Add compatible "st,stm32mp1-hsotg" and associated driver data to manage
the usb33d-supply and the ST specific register for VBus sensing.

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
# Conflicts:
#	drivers/usb/gadget/dwc2_udc_otg.c
Reviewed-by: Lukasz Majewski <lukma@denx.de>
diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt
index 6dc3c4a..eb60ffa 100644
--- a/doc/device-tree-bindings/usb/dwc2.txt
+++ b/doc/device-tree-bindings/usb/dwc2.txt
@@ -37,6 +37,8 @@
 - g-rx-fifo-size: size of rx fifo size in gadget mode.
 - g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode.
 - g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode.
+- usb33d-supply: external VBUS and ID sensing comparators supply, in order to
+  perform OTG operation, used on STM32MP1 SoCs.
 
 Deprecated properties:
 - g-use-dma: gadget DMA mode is automatically detected
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index 106dec5..3fdaa10 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -942,6 +942,7 @@
 	struct reset_ctl_bulk	resets;
 	struct phy *phys;
 	int num_phys;
+	struct udevice *usb33d_supply;
 };
 
 int dm_usb_gadget_handle_interrupts(struct udevice *dev)
@@ -1036,6 +1037,8 @@
 {
 	struct dwc2_plat_otg_data *platdata = dev_get_platdata(dev);
 	int node = dev_of_offset(dev);
+	ulong drvdata;
+	void (*set_params)(struct dwc2_plat_otg_data *data);
 
 	if (usb_get_dr_mode(node) != USB_DR_MODE_PERIPHERAL) {
 		dev_dbg(dev, "Invalid mode\n");
@@ -1052,9 +1055,28 @@
 	platdata->force_b_session_valid =
 		dev_read_bool(dev, "force-b-session-valid");
 
+	/* force platdata according compatible */
+	drvdata = dev_get_driver_data(dev);
+	if (drvdata) {
+		set_params = (void *)drvdata;
+		set_params(platdata);
+	}
+
 	return 0;
 }
 
+static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_plat_otg_data *p)
+{
+	p->activate_stm_id_vb_detection = true;
+	p->usb_gusbcfg =
+		0 << 15		/* PHY Low Power Clock sel*/
+		| 0x9 << 10	/* USB Turnaround time (0x9 for HS phy) */
+		| 0 << 9	/* [0:HNP disable,1:HNP enable]*/
+		| 0 << 8	/* [0:SRP disable 1:SRP enable]*/
+		| 0 << 6	/* 0: high speed utmi+, 1: full speed serial*/
+		| 0x7 << 0;	/* FS timeout calibration**/
+}
+
 static int dwc2_udc_otg_reset_init(struct udevice *dev,
 				   struct reset_ctl_bulk *resets)
 {
@@ -1122,6 +1144,26 @@
 	if (ret)
 		return ret;
 
+	if (CONFIG_IS_ENABLED(DM_REGULATOR) &&
+	    platdata->activate_stm_id_vb_detection &&
+	    !platdata->force_b_session_valid) {
+		ret = device_get_supply_regulator(dev, "usb33d-supply",
+						  &priv->usb33d_supply);
+		if (ret) {
+			dev_err(dev, "can't get voltage level detector supply\n");
+			return ret;
+		}
+		ret = regulator_set_enable(priv->usb33d_supply, true);
+		if (ret) {
+			dev_err(dev, "can't enable voltage level detector supply\n");
+			return ret;
+		}
+		/* Enable vbus sensing */
+		setbits_le32(&usbotg_reg->ggpio,
+			     GGPIO_STM32_OTG_GCCFG_VBDEN |
+			     GGPIO_STM32_OTG_GCCFG_IDEN);
+	}
+
 	if (platdata->force_b_session_valid)
 		/* Override B session bits : value and enable */
 		setbits_le32(&usbotg_reg->gotgctl,  B_VALOEN | B_VALOVAL);
@@ -1154,6 +1196,9 @@
 
 static const struct udevice_id dwc2_udc_otg_ids[] = {
 	{ .compatible = "snps,dwc2" },
+	{ .compatible = "st,stm32mp1-hsotg",
+	  .data = (ulong)dwc2_set_stm32mp1_hsotg_params },
+	{},
 };
 
 U_BOOT_DRIVER(dwc2_udc_otg) = {
diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h
index a389923..b2a28d7 100644
--- a/drivers/usb/gadget/dwc2_udc_otg_regs.h
+++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h
@@ -60,8 +60,9 @@
 	u32 grxstsp; /* Receive Status Debug Pop/Status Pop */
 	u32 grxfsiz; /* Receive FIFO Size */
 	u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */
-
-	u8  res1[36];
+	u8  res0[12];
+	u32 ggpio;     /* 0x038 */
+	u8  res1[20];
 	u32 ghwcfg4; /* User HW Config4 */
 	u8  res2[176];
 	u32 dieptxf[15]; /* Device Periodic Transmit FIFO size register */
@@ -280,4 +281,9 @@
 /* User HW Config4 */
 #define GHWCFG4_NUM_IN_EPS_MASK		(0xf << 26)
 #define GHWCFG4_NUM_IN_EPS_SHIFT	26
+
+/* OTG general core configuration register (OTG_GCCFG:0x38) for STM32MP1 */
+#define GGPIO_STM32_OTG_GCCFG_VBDEN               BIT(21)
+#define GGPIO_STM32_OTG_GCCFG_IDEN                BIT(22)
+
 #endif
diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h
index 369f6fb..a6c1221 100644
--- a/include/usb/dwc2_udc.h
+++ b/include/usb/dwc2_udc.h
@@ -26,6 +26,7 @@
 	unsigned int	tx_fifo_sz_array[DWC2_MAX_HW_ENDPOINTS];
 	unsigned char   tx_fifo_sz_nb;
 	bool		force_b_session_valid;
+	bool		activate_stm_id_vb_detection;
 };
 
 int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata);