usb: dwc2: add support for STM32MP1
authorPatrick Delaunay <patrick.delaunay@st.com>
Fri, 29 Mar 2019 14:42:21 +0000 (15:42 +0100)
committerMarek Vasut <marex@denx.de>
Sun, 21 Apr 2019 08:26:52 +0000 (10:26 +0200)
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>
doc/device-tree-bindings/usb/dwc2.txt
drivers/usb/gadget/dwc2_udc_otg.c
drivers/usb/gadget/dwc2_udc_otg_regs.h
include/usb/dwc2_udc.h

index 6dc3c4a..eb60ffa 100644 (file)
@@ -37,6 +37,8 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties
 - 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
index 106dec5..3fdaa10 100644 (file)
@@ -942,6 +942,7 @@ struct dwc2_priv_data {
        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 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev)
 {
        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 @@ static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev)
        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 @@ static int dwc2_udc_otg_probe(struct udevice *dev)
        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 int dwc2_udc_otg_remove(struct udevice *dev)
 
 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) = {
index a389923..b2a28d7 100644 (file)
@@ -60,8 +60,9 @@ struct dwc2_usbotg_reg {
        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 @@ struct dwc2_usbotg_reg {
 /* 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
index 369f6fb..a6c1221 100644 (file)
@@ -26,6 +26,7 @@ struct dwc2_plat_otg_data {
        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);