Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc3 / dwc3-exynos.c
index 3951a65fea048c51d6fec6b2eda72563fff5cd8a..7bd0a95b2815425d8e088dc39b83e7106177131f 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
-#include <linux/platform_data/dwc3-exynos.h>
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
 #include <linux/usb/otg.h>
@@ -35,6 +34,9 @@ struct dwc3_exynos {
        struct device           *dev;
 
        struct clk              *clk;
+       struct clk              *susp_clk;
+       struct clk              *axius_clk;
+
        struct regulator        *vdd33;
        struct regulator        *vdd10;
 };
@@ -106,7 +108,6 @@ static int dwc3_exynos_remove_child(struct device *dev, void *unused)
 static int dwc3_exynos_probe(struct platform_device *pdev)
 {
        struct dwc3_exynos      *exynos;
-       struct clk              *clk;
        struct device           *dev = &pdev->dev;
        struct device_node      *node = dev->of_node;
 
@@ -133,16 +134,32 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
                return ret;
        }
 
-       clk = devm_clk_get(dev, "usbdrd30");
-       if (IS_ERR(clk)) {
+       exynos->dev     = dev;
+
+       exynos->clk = devm_clk_get(dev, "usbdrd30");
+       if (IS_ERR(exynos->clk)) {
                dev_err(dev, "couldn't get clock\n");
                return -EINVAL;
        }
+       clk_prepare_enable(exynos->clk);
 
-       exynos->dev     = dev;
-       exynos->clk     = clk;
+       exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
+       if (IS_ERR(exynos->susp_clk)) {
+               dev_dbg(dev, "no suspend clk specified\n");
+               exynos->susp_clk = NULL;
+       }
+       clk_prepare_enable(exynos->susp_clk);
 
-       clk_prepare_enable(exynos->clk);
+       if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) {
+               exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
+               if (IS_ERR(exynos->axius_clk)) {
+                       dev_err(dev, "no AXI UpScaler clk specified\n");
+                       return -ENODEV;
+               }
+               clk_prepare_enable(exynos->axius_clk);
+       } else {
+               exynos->axius_clk = NULL;
+       }
 
        exynos->vdd33 = devm_regulator_get(dev, "vdd33");
        if (IS_ERR(exynos->vdd33)) {
@@ -185,7 +202,9 @@ err4:
 err3:
        regulator_disable(exynos->vdd33);
 err2:
-       clk_disable_unprepare(clk);
+       clk_disable_unprepare(exynos->axius_clk);
+       clk_disable_unprepare(exynos->susp_clk);
+       clk_disable_unprepare(exynos->clk);
        return ret;
 }
 
@@ -197,6 +216,8 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
        platform_device_unregister(exynos->usb2_phy);
        platform_device_unregister(exynos->usb3_phy);
 
+       clk_disable_unprepare(exynos->axius_clk);
+       clk_disable_unprepare(exynos->susp_clk);
        clk_disable_unprepare(exynos->clk);
 
        regulator_disable(exynos->vdd33);
@@ -205,19 +226,19 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id exynos_dwc3_match[] = {
        { .compatible = "samsung,exynos5250-dwusb3" },
+       { .compatible = "samsung,exynos7-dwusb3" },
        {},
 };
 MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
-#endif
 
 #ifdef CONFIG_PM_SLEEP
 static int dwc3_exynos_suspend(struct device *dev)
 {
        struct dwc3_exynos *exynos = dev_get_drvdata(dev);
 
+       clk_disable(exynos->axius_clk);
        clk_disable(exynos->clk);
 
        regulator_disable(exynos->vdd33);
@@ -243,6 +264,7 @@ static int dwc3_exynos_resume(struct device *dev)
        }
 
        clk_enable(exynos->clk);
+       clk_enable(exynos->axius_clk);
 
        /* runtime set active to reflect active state. */
        pm_runtime_disable(dev);
@@ -266,7 +288,7 @@ static struct platform_driver dwc3_exynos_driver = {
        .remove         = dwc3_exynos_remove,
        .driver         = {
                .name   = "exynos-dwc3",
-               .of_match_table = of_match_ptr(exynos_dwc3_match),
+               .of_match_table = exynos_dwc3_match,
                .pm     = DEV_PM_OPS,
        },
 };