phy: core: Support regulator supply for PHY power
authorRoger Quadros <rogerq@ti.com>
Fri, 4 Jul 2014 09:55:45 +0000 (12:55 +0300)
committerKishon Vijay Abraham I <kishon@ti.com>
Tue, 22 Jul 2014 07:16:10 +0000 (12:46 +0530)
Some PHYs can be powered by an external power regulator.
e.g. USB_HS PHY on DRA7 SoC. Make the PHY core support a
power regulator.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
drivers/phy/phy-core.c
include/linux/phy/phy.h

index 49c446530101e2565b3f31b05b814c9a5b57c8ff..75c97396dbfad69b20386a60670d614850142710 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/phy/phy.h>
 #include <linux/idr.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 
 static struct class *phy_class;
 static DEFINE_MUTEX(phy_provider_mutex);
@@ -226,6 +227,12 @@ int phy_power_on(struct phy *phy)
        if (!phy)
                return 0;
 
+       if (phy->pwr) {
+               ret = regulator_enable(phy->pwr);
+               if (ret)
+                       return ret;
+       }
+
        ret = phy_pm_runtime_get_sync(phy);
        if (ret < 0 && ret != -ENOTSUPP)
                return ret;
@@ -247,6 +254,8 @@ int phy_power_on(struct phy *phy)
 out:
        mutex_unlock(&phy->mutex);
        phy_pm_runtime_put_sync(phy);
+       if (phy->pwr)
+               regulator_disable(phy->pwr);
 
        return ret;
 }
@@ -272,6 +281,9 @@ int phy_power_off(struct phy *phy)
        mutex_unlock(&phy->mutex);
        phy_pm_runtime_put(phy);
 
+       if (phy->pwr)
+               regulator_disable(phy->pwr);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(phy_power_off);
@@ -588,6 +600,16 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
                goto free_phy;
        }
 
+       /* phy-supply */
+       phy->pwr = regulator_get_optional(dev, "phy");
+       if (IS_ERR(phy->pwr)) {
+               if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) {
+                       ret = -EPROBE_DEFER;
+                       goto free_ida;
+               }
+               phy->pwr = NULL;
+       }
+
        device_initialize(&phy->dev);
        mutex_init(&phy->mutex);
 
@@ -617,6 +639,9 @@ put_dev:
        put_device(&phy->dev);  /* calls phy_release() which frees resources */
        return ERR_PTR(ret);
 
+free_ida:
+       ida_simple_remove(&phy_ida, phy->id);
+
 free_phy:
        kfree(phy);
        return ERR_PTR(ret);
@@ -800,6 +825,7 @@ static void phy_release(struct device *dev)
 
        phy = to_phy(dev);
        dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
+       regulator_put(phy->pwr);
        ida_simple_remove(&phy_ida, phy->id);
        kfree(phy);
 }
index 2760744cb2a75ff59e3d172a6dd864ef42b32106..9a86945247421db41f0f0e0e248cc991d2676f1d 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/of.h>
 #include <linux/device.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 
 struct phy;
 
@@ -65,6 +66,7 @@ struct phy {
        int                     init_count;
        int                     power_count;
        struct phy_attrs        attrs;
+       struct regulator        *pwr;
 };
 
 /**