usb: ehci-platform: add optional reset controller retrieval
[firefly-linux-kernel-4.4.55.git] / drivers / usb / host / ehci-platform.c
index c7dd93aad20c59c4ace574a5e25a507bb267baa1..2f5b9ce3e042f7473b359740a73bf782090ba936 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/of.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
+#include <linux/reset.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/usb/ehci_pdriver.h>
@@ -41,6 +42,7 @@
 
 struct ehci_platform_priv {
        struct clk *clks[EHCI_MAX_CLKS];
+       struct reset_control *rst;
        struct phy *phy;
 };
 
@@ -208,6 +210,18 @@ static int ehci_platform_probe(struct platform_device *dev)
                }
        }
 
+       priv->rst = devm_reset_control_get_optional(&dev->dev, NULL);
+       if (IS_ERR(priv->rst)) {
+               err = PTR_ERR(priv->rst);
+               if (err == -EPROBE_DEFER)
+                       goto err_put_clks;
+               priv->rst = NULL;
+       } else {
+               err = reset_control_deassert(priv->rst);
+               if (err)
+                       goto err_put_clks;
+       }
+
        if (pdata->big_endian_desc)
                ehci->big_endian_desc = 1;
        if (pdata->big_endian_mmio)
@@ -218,7 +232,7 @@ static int ehci_platform_probe(struct platform_device *dev)
                dev_err(&dev->dev,
                        "Error: CONFIG_USB_EHCI_BIG_ENDIAN_MMIO not set\n");
                err = -EINVAL;
-               goto err_put_clks;
+               goto err_reset;
        }
 #endif
 #ifndef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
@@ -226,14 +240,14 @@ static int ehci_platform_probe(struct platform_device *dev)
                dev_err(&dev->dev,
                        "Error: CONFIG_USB_EHCI_BIG_ENDIAN_DESC not set\n");
                err = -EINVAL;
-               goto err_put_clks;
+               goto err_reset;
        }
 #endif
 
        if (pdata->power_on) {
                err = pdata->power_on(dev);
                if (err < 0)
-                       goto err_put_clks;
+                       goto err_reset;
        }
 
        hcd->rsrc_start = res_mem->start;
@@ -256,6 +270,9 @@ static int ehci_platform_probe(struct platform_device *dev)
 err_power:
        if (pdata->power_off)
                pdata->power_off(dev);
+err_reset:
+       if (priv->rst)
+               reset_control_assert(priv->rst);
 err_put_clks:
        while (--clk >= 0)
                clk_put(priv->clks[clk]);
@@ -280,6 +297,9 @@ static int ehci_platform_remove(struct platform_device *dev)
        if (pdata->power_off)
                pdata->power_off(dev);
 
+       if (priv->rst)
+               reset_control_assert(priv->rst);
+
        for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
                clk_put(priv->clks[clk]);