These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / usb / dwc3 / core.c
index 2bbab3d..22b4797 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/of.h>
 #include <linux/acpi.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -116,6 +117,59 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
        return 0;
 }
 
+/**
+ * dwc3_soft_reset - Issue soft reset
+ * @dwc: Pointer to our controller context structure
+ */
+static int dwc3_soft_reset(struct dwc3 *dwc)
+{
+       unsigned long timeout;
+       u32 reg;
+
+       timeout = jiffies + msecs_to_jiffies(500);
+       dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
+       do {
+               reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+               if (!(reg & DWC3_DCTL_CSFTRST))
+                       break;
+
+               if (time_after(jiffies, timeout)) {
+                       dev_err(dwc->dev, "Reset Timed Out\n");
+                       return -ETIMEDOUT;
+               }
+
+               cpu_relax();
+       } while (true);
+
+       return 0;
+}
+
+/*
+ * dwc3_frame_length_adjustment - Adjusts frame length if required
+ * @dwc3: Pointer to our controller context structure
+ * @fladj: Value of GFLADJ_30MHZ to adjust frame length
+ */
+static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj)
+{
+       u32 reg;
+       u32 dft;
+
+       if (dwc->revision < DWC3_REVISION_250A)
+               return;
+
+       if (fladj == 0)
+               return;
+
+       reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
+       dft = reg & DWC3_GFLADJ_30MHZ_MASK;
+       if (!dev_WARN_ONCE(dwc->dev, dft == fladj,
+           "request value same as default, ignoring\n")) {
+               reg &= ~DWC3_GFLADJ_30MHZ_MASK;
+               reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj;
+               dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
+       }
+}
+
 /**
  * dwc3_free_one_event_buffer - Frees one event buffer
  * @dwc: Pointer to our controller context structure
@@ -367,10 +421,15 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
 /**
  * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
  * @dwc: Pointer to our controller context structure
+ *
+ * Returns 0 on success. The USB PHY interfaces are configured but not
+ * initialized. The PHY interfaces and the PHYs get initialized together with
+ * the core in dwc3_core_init.
  */
-static void dwc3_phy_setup(struct dwc3 *dwc)
+static int dwc3_phy_setup(struct dwc3 *dwc)
 {
        u32 reg;
+       int ret;
 
        reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
 
@@ -409,10 +468,41 @@ static void dwc3_phy_setup(struct dwc3 *dwc)
 
        dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
 
-       mdelay(100);
-
        reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
 
+       /* Select the HS PHY interface */
+       switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) {
+       case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI:
+               if (dwc->hsphy_interface &&
+                               !strncmp(dwc->hsphy_interface, "utmi", 4)) {
+                       reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI;
+                       break;
+               } else if (dwc->hsphy_interface &&
+                               !strncmp(dwc->hsphy_interface, "ulpi", 4)) {
+                       reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
+                       dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+               } else {
+                       /* Relying on default value. */
+                       if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI))
+                               break;
+               }
+               /* FALLTHROUGH */
+       case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
+               /* Making sure the interface and PHY are operational */
+               ret = dwc3_soft_reset(dwc);
+               if (ret)
+                       return ret;
+
+               udelay(1);
+
+               ret = dwc3_ulpi_init(dwc);
+               if (ret)
+                       return ret;
+               /* FALLTHROUGH */
+       default:
+               break;
+       }
+
        /*
         * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
         * '0' during coreConsultant configuration. So default value will
@@ -425,9 +515,12 @@ static void dwc3_phy_setup(struct dwc3 *dwc)
        if (dwc->dis_u2_susphy_quirk)
                reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
 
+       if (dwc->dis_enblslpm_quirk)
+               reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
+
        dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 
-       mdelay(100);
+       return 0;
 }
 
 /**
@@ -438,19 +531,24 @@ static void dwc3_phy_setup(struct dwc3 *dwc)
  */
 static int dwc3_core_init(struct dwc3 *dwc)
 {
-       unsigned long           timeout;
        u32                     hwparams4 = dwc->hwparams.hwparams4;
        u32                     reg;
        int                     ret;
 
        reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
        /* This should read as U3 followed by revision number */
-       if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
+       if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) {
+               /* Detected DWC_usb3 IP */
+               dwc->revision = reg;
+       } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) {
+               /* Detected DWC_usb31 IP */
+               dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER);
+               dwc->revision |= DWC3_REVISION_IS_DWC31;
+       } else {
                dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
                ret = -ENODEV;
                goto err0;
        }
-       dwc->revision = reg;
 
        /*
         * Write Linux Version Code to our GUID register so it's easy to figure
@@ -466,21 +564,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
        }
 
        /* issue device SoftReset too */
-       timeout = jiffies + msecs_to_jiffies(500);
-       dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
-       do {
-               reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-               if (!(reg & DWC3_DCTL_CSFTRST))
-                       break;
-
-               if (time_after(jiffies, timeout)) {
-                       dev_err(dwc->dev, "Reset Timed Out\n");
-                       ret = -ETIMEDOUT;
-                       goto err0;
-               }
-
-               cpu_relax();
-       } while (true);
+       ret = dwc3_soft_reset(dwc);
+       if (ret)
+               goto err0;
 
        ret = dwc3_core_soft_reset(dwc);
        if (ret)
@@ -555,8 +641,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
 
        dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 
-       dwc3_phy_setup(dwc);
-
        ret = dwc3_alloc_scratch_buffers(dwc);
        if (ret)
                goto err1;
@@ -725,12 +809,12 @@ static int dwc3_probe(struct platform_device *pdev)
 {
        struct device           *dev = &pdev->dev;
        struct dwc3_platform_data *pdata = dev_get_platdata(dev);
-       struct device_node      *node = dev->of_node;
        struct resource         *res;
        struct dwc3             *dwc;
        u8                      lpm_nyet_threshold;
        u8                      tx_de_emphasis;
        u8                      hird_threshold;
+       u32                     fladj = 0;
 
        int                     ret;
 
@@ -794,49 +878,56 @@ static int dwc3_probe(struct platform_device *pdev)
         */
        hird_threshold = 12;
 
-       if (node) {
-               dwc->maximum_speed = of_usb_get_maximum_speed(node);
-               dwc->has_lpm_erratum = of_property_read_bool(node,
+       dwc->maximum_speed = usb_get_maximum_speed(dev);
+       dwc->dr_mode = usb_get_dr_mode(dev);
+
+       dwc->has_lpm_erratum = device_property_read_bool(dev,
                                "snps,has-lpm-erratum");
-               of_property_read_u8(node, "snps,lpm-nyet-threshold",
+       device_property_read_u8(dev, "snps,lpm-nyet-threshold",
                                &lpm_nyet_threshold);
-               dwc->is_utmi_l1_suspend = of_property_read_bool(node,
+       dwc->is_utmi_l1_suspend = device_property_read_bool(dev,
                                "snps,is-utmi-l1-suspend");
-               of_property_read_u8(node, "snps,hird-threshold",
+       device_property_read_u8(dev, "snps,hird-threshold",
                                &hird_threshold);
-               dwc->usb3_lpm_capable = of_property_read_bool(node,
+       dwc->usb3_lpm_capable = device_property_read_bool(dev,
                                "snps,usb3_lpm_capable");
 
-               dwc->needs_fifo_resize = of_property_read_bool(node,
+       dwc->needs_fifo_resize = device_property_read_bool(dev,
                                "tx-fifo-resize");
-               dwc->dr_mode = of_usb_get_dr_mode(node);
 
-               dwc->disable_scramble_quirk = of_property_read_bool(node,
+       dwc->disable_scramble_quirk = device_property_read_bool(dev,
                                "snps,disable_scramble_quirk");
-               dwc->u2exit_lfps_quirk = of_property_read_bool(node,
+       dwc->u2exit_lfps_quirk = device_property_read_bool(dev,
                                "snps,u2exit_lfps_quirk");
-               dwc->u2ss_inp3_quirk = of_property_read_bool(node,
+       dwc->u2ss_inp3_quirk = device_property_read_bool(dev,
                                "snps,u2ss_inp3_quirk");
-               dwc->req_p1p2p3_quirk = of_property_read_bool(node,
+       dwc->req_p1p2p3_quirk = device_property_read_bool(dev,
                                "snps,req_p1p2p3_quirk");
-               dwc->del_p1p2p3_quirk = of_property_read_bool(node,
+       dwc->del_p1p2p3_quirk = device_property_read_bool(dev,
                                "snps,del_p1p2p3_quirk");
-               dwc->del_phy_power_chg_quirk = of_property_read_bool(node,
+       dwc->del_phy_power_chg_quirk = device_property_read_bool(dev,
                                "snps,del_phy_power_chg_quirk");
-               dwc->lfps_filter_quirk = of_property_read_bool(node,
+       dwc->lfps_filter_quirk = device_property_read_bool(dev,
                                "snps,lfps_filter_quirk");
-               dwc->rx_detect_poll_quirk = of_property_read_bool(node,
+       dwc->rx_detect_poll_quirk = device_property_read_bool(dev,
                                "snps,rx_detect_poll_quirk");
-               dwc->dis_u3_susphy_quirk = of_property_read_bool(node,
+       dwc->dis_u3_susphy_quirk = device_property_read_bool(dev,
                                "snps,dis_u3_susphy_quirk");
-               dwc->dis_u2_susphy_quirk = of_property_read_bool(node,
+       dwc->dis_u2_susphy_quirk = device_property_read_bool(dev,
                                "snps,dis_u2_susphy_quirk");
+       dwc->dis_enblslpm_quirk = device_property_read_bool(dev,
+                               "snps,dis_enblslpm_quirk");
 
-               dwc->tx_de_emphasis_quirk = of_property_read_bool(node,
+       dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
                                "snps,tx_de_emphasis_quirk");
-               of_property_read_u8(node, "snps,tx_de_emphasis",
+       device_property_read_u8(dev, "snps,tx_de_emphasis",
                                &tx_de_emphasis);
-       } else if (pdata) {
+       device_property_read_string(dev, "snps,hsphy_interface",
+                                   &dwc->hsphy_interface);
+       device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
+                                &fladj);
+
+       if (pdata) {
                dwc->maximum_speed = pdata->maximum_speed;
                dwc->has_lpm_erratum = pdata->has_lpm_erratum;
                if (pdata->lpm_nyet_threshold)
@@ -859,10 +950,14 @@ static int dwc3_probe(struct platform_device *pdev)
                dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk;
                dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk;
                dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk;
+               dwc->dis_enblslpm_quirk = pdata->dis_enblslpm_quirk;
 
                dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk;
                if (pdata->tx_de_emphasis)
                        tx_de_emphasis = pdata->tx_de_emphasis;
+
+               dwc->hsphy_interface = pdata->hsphy_interface;
+               fladj = pdata->fladj_value;
        }
 
        /* default to superspeed if no maximum_speed passed */
@@ -875,12 +970,18 @@ static int dwc3_probe(struct platform_device *pdev)
        dwc->hird_threshold = hird_threshold
                | (dwc->is_utmi_l1_suspend << 4);
 
+       platform_set_drvdata(pdev, dwc);
+       dwc3_cache_hwparams(dwc);
+
+       ret = dwc3_phy_setup(dwc);
+       if (ret)
+               goto err0;
+
        ret = dwc3_core_get_phy(dwc);
        if (ret)
                goto err0;
 
        spin_lock_init(&dwc->lock);
-       platform_set_drvdata(pdev, dwc);
 
        if (!dev->dma_mask) {
                dev->dma_mask = dev->parent->dma_mask;
@@ -892,8 +993,6 @@ static int dwc3_probe(struct platform_device *pdev)
        pm_runtime_get_sync(dev);
        pm_runtime_forbid(dev);
 
-       dwc3_cache_hwparams(dwc);
-
        ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
        if (ret) {
                dev_err(dwc->dev, "failed to allocate event buffers\n");
@@ -915,6 +1014,9 @@ static int dwc3_probe(struct platform_device *pdev)
                goto err1;
        }
 
+       /* Adjust Frame Length */
+       dwc3_frame_length_adjustment(dwc, fladj);
+
        usb_phy_set_suspend(dwc->usb2_phy, 0);
        usb_phy_set_suspend(dwc->usb3_phy, 0);
        ret = phy_power_on(dwc->usb2_generic_phy);
@@ -964,6 +1066,7 @@ err2:
 
 err1:
        dwc3_free_event_buffers(dwc);
+       dwc3_ulpi_exit(dwc);
 
 err0:
        /*
@@ -999,6 +1102,7 @@ static int dwc3_remove(struct platform_device *pdev)
        phy_power_off(dwc->usb3_generic_phy);
 
        dwc3_core_exit(dwc);
+       dwc3_ulpi_exit(dwc);
 
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
@@ -1033,6 +1137,8 @@ static int dwc3_suspend(struct device *dev)
        phy_exit(dwc->usb2_generic_phy);
        phy_exit(dwc->usb3_generic_phy);
 
+       pinctrl_pm_select_sleep_state(dev);
+
        return 0;
 }
 
@@ -1042,6 +1148,8 @@ static int dwc3_resume(struct device *dev)
        unsigned long   flags;
        int             ret;
 
+       pinctrl_pm_select_default_state(dev);
+
        usb_phy_init(dwc->usb3_phy);
        usb_phy_init(dwc->usb2_phy);
        ret = phy_init(dwc->usb2_generic_phy);