diff options
author | Roger Quadros <rogerq@ti.com> | 2014-07-04 05:55:45 -0400 |
---|---|---|
committer | Kishon Vijay Abraham I <kishon@ti.com> | 2014-07-22 03:16:10 -0400 |
commit | 3be88125d85df587085b0be0a5c0e9953eb5ed6b (patch) | |
tree | c0fd6fcb0c03681d6442381480e6f30c8d6f250d | |
parent | 016e0d3cb72c1433810fd85a7a7c0946e710d3d6 (diff) |
phy: core: Support regulator supply for PHY power
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>
-rw-r--r-- | drivers/phy/phy-core.c | 26 | ||||
-rw-r--r-- | include/linux/phy/phy.h | 2 |
2 files changed, 28 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 @@ | |||
21 | #include <linux/phy/phy.h> | 21 | #include <linux/phy/phy.h> |
22 | #include <linux/idr.h> | 22 | #include <linux/idr.h> |
23 | #include <linux/pm_runtime.h> | 23 | #include <linux/pm_runtime.h> |
24 | #include <linux/regulator/consumer.h> | ||
24 | 25 | ||
25 | static struct class *phy_class; | 26 | static struct class *phy_class; |
26 | static DEFINE_MUTEX(phy_provider_mutex); | 27 | static DEFINE_MUTEX(phy_provider_mutex); |
@@ -226,6 +227,12 @@ int phy_power_on(struct phy *phy) | |||
226 | if (!phy) | 227 | if (!phy) |
227 | return 0; | 228 | return 0; |
228 | 229 | ||
230 | if (phy->pwr) { | ||
231 | ret = regulator_enable(phy->pwr); | ||
232 | if (ret) | ||
233 | return ret; | ||
234 | } | ||
235 | |||
229 | ret = phy_pm_runtime_get_sync(phy); | 236 | ret = phy_pm_runtime_get_sync(phy); |
230 | if (ret < 0 && ret != -ENOTSUPP) | 237 | if (ret < 0 && ret != -ENOTSUPP) |
231 | return ret; | 238 | return ret; |
@@ -247,6 +254,8 @@ int phy_power_on(struct phy *phy) | |||
247 | out: | 254 | out: |
248 | mutex_unlock(&phy->mutex); | 255 | mutex_unlock(&phy->mutex); |
249 | phy_pm_runtime_put_sync(phy); | 256 | phy_pm_runtime_put_sync(phy); |
257 | if (phy->pwr) | ||
258 | regulator_disable(phy->pwr); | ||
250 | 259 | ||
251 | return ret; | 260 | return ret; |
252 | } | 261 | } |
@@ -272,6 +281,9 @@ int phy_power_off(struct phy *phy) | |||
272 | mutex_unlock(&phy->mutex); | 281 | mutex_unlock(&phy->mutex); |
273 | phy_pm_runtime_put(phy); | 282 | phy_pm_runtime_put(phy); |
274 | 283 | ||
284 | if (phy->pwr) | ||
285 | regulator_disable(phy->pwr); | ||
286 | |||
275 | return 0; | 287 | return 0; |
276 | } | 288 | } |
277 | EXPORT_SYMBOL_GPL(phy_power_off); | 289 | EXPORT_SYMBOL_GPL(phy_power_off); |
@@ -588,6 +600,16 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops, | |||
588 | goto free_phy; | 600 | goto free_phy; |
589 | } | 601 | } |
590 | 602 | ||
603 | /* phy-supply */ | ||
604 | phy->pwr = regulator_get_optional(dev, "phy"); | ||
605 | if (IS_ERR(phy->pwr)) { | ||
606 | if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) { | ||
607 | ret = -EPROBE_DEFER; | ||
608 | goto free_ida; | ||
609 | } | ||
610 | phy->pwr = NULL; | ||
611 | } | ||
612 | |||
591 | device_initialize(&phy->dev); | 613 | device_initialize(&phy->dev); |
592 | mutex_init(&phy->mutex); | 614 | mutex_init(&phy->mutex); |
593 | 615 | ||
@@ -617,6 +639,9 @@ put_dev: | |||
617 | put_device(&phy->dev); /* calls phy_release() which frees resources */ | 639 | put_device(&phy->dev); /* calls phy_release() which frees resources */ |
618 | return ERR_PTR(ret); | 640 | return ERR_PTR(ret); |
619 | 641 | ||
642 | free_ida: | ||
643 | ida_simple_remove(&phy_ida, phy->id); | ||
644 | |||
620 | free_phy: | 645 | free_phy: |
621 | kfree(phy); | 646 | kfree(phy); |
622 | return ERR_PTR(ret); | 647 | return ERR_PTR(ret); |
@@ -800,6 +825,7 @@ static void phy_release(struct device *dev) | |||
800 | 825 | ||
801 | phy = to_phy(dev); | 826 | phy = to_phy(dev); |
802 | dev_vdbg(dev, "releasing '%s'\n", dev_name(dev)); | 827 | dev_vdbg(dev, "releasing '%s'\n", dev_name(dev)); |
828 | regulator_put(phy->pwr); | ||
803 | ida_simple_remove(&phy_ida, phy->id); | 829 | ida_simple_remove(&phy_ida, phy->id); |
804 | kfree(phy); | 830 | kfree(phy); |
805 | } | 831 | } |
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 2760744cb2a7..9a8694524742 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/of.h> | 18 | #include <linux/of.h> |
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
21 | #include <linux/regulator/consumer.h> | ||
21 | 22 | ||
22 | struct phy; | 23 | struct phy; |
23 | 24 | ||
@@ -65,6 +66,7 @@ struct phy { | |||
65 | int init_count; | 66 | int init_count; |
66 | int power_count; | 67 | int power_count; |
67 | struct phy_attrs attrs; | 68 | struct phy_attrs attrs; |
69 | struct regulator *pwr; | ||
68 | }; | 70 | }; |
69 | 71 | ||
70 | /** | 72 | /** |