Merge tag 'upstream-3.13-rc1' of git://git.infradead.org/linux-ubifs
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / usb / phy / phy-generic.c
index efe59f3..fce3a9e 100644 (file)
@@ -35,6 +35,9 @@
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
 
 #include "phy-generic.h"
 
@@ -64,6 +67,23 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
        return 0;
 }
 
+static void nop_reset_set(struct usb_phy_gen_xceiv *nop, int asserted)
+{
+       int value;
+
+       if (!gpio_is_valid(nop->gpio_reset))
+               return;
+
+       value = asserted;
+       if (nop->reset_active_low)
+               value = !value;
+
+       gpio_set_value_cansleep(nop->gpio_reset, value);
+
+       if (!asserted)
+               usleep_range(10000, 20000);
+}
+
 int usb_gen_phy_init(struct usb_phy *phy)
 {
        struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
@@ -74,13 +94,10 @@ int usb_gen_phy_init(struct usb_phy *phy)
        }
 
        if (!IS_ERR(nop->clk))
-               clk_enable(nop->clk);
+               clk_prepare_enable(nop->clk);
 
-       if (!IS_ERR(nop->reset)) {
-               /* De-assert RESET */
-               if (regulator_enable(nop->reset))
-                       dev_err(phy->dev, "Failed to de-assert reset\n");
-       }
+       /* De-assert RESET */
+       nop_reset_set(nop, 0);
 
        return 0;
 }
@@ -90,14 +107,11 @@ void usb_gen_phy_shutdown(struct usb_phy *phy)
 {
        struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
 
-       if (!IS_ERR(nop->reset)) {
-               /* Assert RESET */
-               if (regulator_disable(nop->reset))
-                       dev_err(phy->dev, "Failed to assert reset\n");
-       }
+       /* Assert RESET */
+       nop_reset_set(nop, 1);
 
        if (!IS_ERR(nop->clk))
-               clk_disable(nop->clk);
+               clk_disable_unprepare(nop->clk);
 
        if (!IS_ERR(nop->vcc)) {
                if (regulator_disable(nop->vcc))
@@ -136,8 +150,7 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
 }
 
 int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
-               enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
-               bool needs_reset)
+               enum usb_phy_type type, u32 clk_rate, bool needs_vcc)
 {
        int err;
 
@@ -160,14 +173,6 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
                }
        }
 
-       if (!IS_ERR(nop->clk)) {
-               err = clk_prepare(nop->clk);
-               if (err) {
-                       dev_err(dev, "Error preparing clock\n");
-                       return err;
-               }
-       }
-
        nop->vcc = devm_regulator_get(dev, "vcc");
        if (IS_ERR(nop->vcc)) {
                dev_dbg(dev, "Error getting vcc regulator: %ld\n",
@@ -176,12 +181,22 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
                        return -EPROBE_DEFER;
        }
 
-       nop->reset = devm_regulator_get(dev, "reset");
-       if (IS_ERR(nop->reset)) {
-               dev_dbg(dev, "Error getting reset regulator: %ld\n",
-                                       PTR_ERR(nop->reset));
-               if (needs_reset)
-                       return -EPROBE_DEFER;
+       if (gpio_is_valid(nop->gpio_reset)) {
+               unsigned long gpio_flags;
+
+               /* Assert RESET */
+               if (nop->reset_active_low)
+                       gpio_flags = GPIOF_OUT_INIT_LOW;
+               else
+                       gpio_flags = GPIOF_OUT_INIT_HIGH;
+
+               err = devm_gpio_request_one(dev, nop->gpio_reset,
+                                               gpio_flags, dev_name(dev));
+               if (err) {
+                       dev_err(dev, "Error requesting RESET GPIO %d\n",
+                                       nop->gpio_reset);
+                       return err;
+               }
        }
 
        nop->dev                = dev;
@@ -200,13 +215,6 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
 }
 EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
 
-void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop)
-{
-       if (!IS_ERR(nop->clk))
-               clk_unprepare(nop->clk);
-}
-EXPORT_SYMBOL_GPL(usb_phy_gen_cleanup_phy);
-
 static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -217,31 +225,36 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
        int err;
        u32 clk_rate = 0;
        bool needs_vcc = false;
-       bool needs_reset = false;
+
+       nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
+       if (!nop)
+               return -ENOMEM;
+
+       nop->reset_active_low = true;   /* default behaviour */
 
        if (dev->of_node) {
                struct device_node *node = dev->of_node;
+               enum of_gpio_flags flags;
 
                if (of_property_read_u32(node, "clock-frequency", &clk_rate))
                        clk_rate = 0;
 
                needs_vcc = of_property_read_bool(node, "vcc-supply");
-               needs_reset = of_property_read_bool(node, "reset-supply");
+               nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios",
+                                                               0, &flags);
+               if (nop->gpio_reset == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
 
        } else if (pdata) {
                type = pdata->type;
                clk_rate = pdata->clk_rate;
                needs_vcc = pdata->needs_vcc;
-               needs_reset = pdata->needs_reset;
+               nop->gpio_reset = pdata->gpio_reset;
        }
 
-       nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
-       if (!nop)
-               return -ENOMEM;
-
-
-       err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc,
-                       needs_reset);
+       err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc);
        if (err)
                return err;
 
@@ -252,15 +265,13 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
        if (err) {
                dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
                        err);
-               goto err_add;
+               return err;
        }
 
        platform_set_drvdata(pdev, nop);
 
        return 0;
 
-err_add:
-       usb_phy_gen_cleanup_phy(nop);
        return err;
 }
 
@@ -268,7 +279,6 @@ static int usb_phy_gen_xceiv_remove(struct platform_device *pdev)
 {
        struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev);
 
-       usb_phy_gen_cleanup_phy(nop);
        usb_remove_phy(&nop->phy);
 
        return 0;