diff options
Diffstat (limited to 'drivers/phy')
-rw-r--r-- | drivers/phy/phy-core.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 49c446530101..75c97396dbfa 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -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); } |