usb: dwc3: Add dwc3_of_parse() to get quirks information from DT
[oweals/u-boot.git] / drivers / usb / dwc3 / core.c
index 2498f0efb1a488aee4854e51072852fde5ad8a4f..5fe5bfae0ed05b88cbc0ccd7eb73e8cc86f25baf 100644 (file)
@@ -581,6 +581,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
        return 0;
 }
 
+static void dwc3_gadget_run(struct dwc3 *dwc)
+{
+       dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_RUN_STOP);
+       mdelay(100);
+}
+
 static void dwc3_core_exit_mode(struct dwc3 *dwc)
 {
        switch (dwc->dr_mode) {
@@ -598,6 +604,13 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
                /* do nothing */
                break;
        }
+
+       /*
+        * switch back to peripheral mode
+        * This enables the phy to enter idle and then, if enabled, suspend.
+        */
+       dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
+       dwc3_gadget_run(dwc);
 }
 
 #define DWC3_ALIGN_MASK                (16 - 1)
@@ -874,7 +887,72 @@ int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys)
 }
 #endif
 
-#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+#if CONFIG_IS_ENABLED(DM_USB)
+void dwc3_of_parse(struct dwc3 *dwc)
+{
+       const u8 *tmp;
+       struct udevice *dev = dwc->dev;
+       u8 lpm_nyet_threshold;
+       u8 tx_de_emphasis;
+       u8 hird_threshold;
+
+       /* default to highest possible threshold */
+       lpm_nyet_threshold = 0xff;
+
+       /* default to -3.5dB de-emphasis */
+       tx_de_emphasis = 1;
+
+       /*
+        * default to assert utmi_sleep_n and use maximum allowed HIRD
+        * threshold value of 0b1100
+        */
+       hird_threshold = 12;
+
+       dwc->has_lpm_erratum = dev_read_bool(dev,
+                               "snps,has-lpm-erratum");
+       tmp = dev_read_u8_array_ptr(dev, "snps,lpm-nyet-threshold", 1);
+       if (tmp)
+               lpm_nyet_threshold = *tmp;
+
+       dwc->is_utmi_l1_suspend = dev_read_bool(dev,
+                               "snps,is-utmi-l1-suspend");
+       tmp = dev_read_u8_array_ptr(dev, "snps,hird-threshold", 1);
+       if (tmp)
+               hird_threshold = *tmp;
+
+       dwc->disable_scramble_quirk = dev_read_bool(dev,
+                               "snps,disable_scramble_quirk");
+       dwc->u2exit_lfps_quirk = dev_read_bool(dev,
+                               "snps,u2exit_lfps_quirk");
+       dwc->u2ss_inp3_quirk = dev_read_bool(dev,
+                               "snps,u2ss_inp3_quirk");
+       dwc->req_p1p2p3_quirk = dev_read_bool(dev,
+                               "snps,req_p1p2p3_quirk");
+       dwc->del_p1p2p3_quirk = dev_read_bool(dev,
+                               "snps,del_p1p2p3_quirk");
+       dwc->del_phy_power_chg_quirk = dev_read_bool(dev,
+                               "snps,del_phy_power_chg_quirk");
+       dwc->lfps_filter_quirk = dev_read_bool(dev,
+                               "snps,lfps_filter_quirk");
+       dwc->rx_detect_poll_quirk = dev_read_bool(dev,
+                               "snps,rx_detect_poll_quirk");
+       dwc->dis_u3_susphy_quirk = dev_read_bool(dev,
+                               "snps,dis_u3_susphy_quirk");
+       dwc->dis_u2_susphy_quirk = dev_read_bool(dev,
+                               "snps,dis_u2_susphy_quirk");
+       dwc->tx_de_emphasis_quirk = dev_read_bool(dev,
+                               "snps,tx_de_emphasis_quirk");
+       tmp = dev_read_u8_array_ptr(dev, "snps,tx_de_emphasis", 1);
+       if (tmp)
+               tx_de_emphasis = *tmp;
+
+       dwc->lpm_nyet_threshold = lpm_nyet_threshold;
+       dwc->tx_de_emphasis = tx_de_emphasis;
+
+       dwc->hird_threshold = hird_threshold
+               | (dwc->is_utmi_l1_suspend << 4);
+}
+
 int dwc3_init(struct dwc3 *dwc)
 {
        int ret;