aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2015-08-21 08:38:37 -0400
committerKishon Vijay Abraham I <kishon@ti.com>2015-10-06 10:51:47 -0400
commita007ddbaef5317f76bec541688e304f31ad9c4b0 (patch)
treea991e43fb013d8b4397beec3c363aac12a083b44
parent6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f (diff)
phy: exynos-usb2: add vbus regulator support
Exynos USB2 PHY has separate power supply, which is usually provided by VBUS regulator. This patch adds support for it. VBUS regulator is optional, to keep compatibility with boards, which have VBUS provided from some always-on power source. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
-rw-r--r--Documentation/devicetree/bindings/phy/samsung-phy.txt3
-rw-r--r--drivers/phy/phy-samsung-usb2.c25
-rw-r--r--drivers/phy/phy-samsung-usb2.h2
3 files changed, 28 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index 60c6f2a633e0..0289d3b07853 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -44,6 +44,9 @@ Required properties:
44 - the "ref" clock is used to get the rate of the clock provided to the 44 - the "ref" clock is used to get the rate of the clock provided to the
45 PHY module 45 PHY module
46 46
47Optional properties:
48- vbus-supply: power-supply phandle for vbus power source
49
47The first phandle argument in the PHY specifier identifies the PHY, its 50The first phandle argument in the PHY specifier identifies the PHY, its
48meaning is compatible dependent. For the currently supported SoCs (Exynos 4210 51meaning is compatible dependent. For the currently supported SoCs (Exynos 4210
49and Exynos 4212) it is as follows: 52and Exynos 4212) it is as follows:
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index f278a9c547e1..1d22d93b552d 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -27,6 +27,13 @@ static int samsung_usb2_phy_power_on(struct phy *phy)
27 27
28 dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n", 28 dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
29 inst->cfg->label); 29 inst->cfg->label);
30
31 if (drv->vbus) {
32 ret = regulator_enable(drv->vbus);
33 if (ret)
34 goto err_regulator;
35 }
36
30 ret = clk_prepare_enable(drv->clk); 37 ret = clk_prepare_enable(drv->clk);
31 if (ret) 38 if (ret)
32 goto err_main_clk; 39 goto err_main_clk;
@@ -48,6 +55,9 @@ err_power_on:
48err_instance_clk: 55err_instance_clk:
49 clk_disable_unprepare(drv->clk); 56 clk_disable_unprepare(drv->clk);
50err_main_clk: 57err_main_clk:
58 if (drv->vbus)
59 regulator_disable(drv->vbus);
60err_regulator:
51 return ret; 61 return ret;
52} 62}
53 63
@@ -55,7 +65,7 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
55{ 65{
56 struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy); 66 struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
57 struct samsung_usb2_phy_driver *drv = inst->drv; 67 struct samsung_usb2_phy_driver *drv = inst->drv;
58 int ret; 68 int ret = 0;
59 69
60 dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n", 70 dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
61 inst->cfg->label); 71 inst->cfg->label);
@@ -68,7 +78,10 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
68 } 78 }
69 clk_disable_unprepare(drv->ref_clk); 79 clk_disable_unprepare(drv->ref_clk);
70 clk_disable_unprepare(drv->clk); 80 clk_disable_unprepare(drv->clk);
71 return 0; 81 if (drv->vbus)
82 ret = regulator_disable(drv->vbus);
83
84 return ret;
72} 85}
73 86
74static const struct phy_ops samsung_usb2_phy_ops = { 87static const struct phy_ops samsung_usb2_phy_ops = {
@@ -203,6 +216,14 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
203 return ret; 216 return ret;
204 } 217 }
205 218
219 drv->vbus = devm_regulator_get(dev, "vbus");
220 if (IS_ERR(drv->vbus)) {
221 ret = PTR_ERR(drv->vbus);
222 if (ret == -EPROBE_DEFER)
223 return ret;
224 drv->vbus = NULL;
225 }
226
206 for (i = 0; i < drv->cfg->num_phys; i++) { 227 for (i = 0; i < drv->cfg->num_phys; i++) {
207 char *label = drv->cfg->phys[i].label; 228 char *label = drv->cfg->phys[i].label;
208 struct samsung_usb2_phy_instance *p = &drv->instances[i]; 229 struct samsung_usb2_phy_instance *p = &drv->instances[i];
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index 44bead9b8f34..6563e7ca0ac4 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -17,6 +17,7 @@
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/regmap.h> 18#include <linux/regmap.h>
19#include <linux/spinlock.h> 19#include <linux/spinlock.h>
20#include <linux/regulator/consumer.h>
20 21
21#define KHZ 1000 22#define KHZ 1000
22#define MHZ (KHZ * KHZ) 23#define MHZ (KHZ * KHZ)
@@ -37,6 +38,7 @@ struct samsung_usb2_phy_driver {
37 const struct samsung_usb2_phy_config *cfg; 38 const struct samsung_usb2_phy_config *cfg;
38 struct clk *clk; 39 struct clk *clk;
39 struct clk *ref_clk; 40 struct clk *ref_clk;
41 struct regulator *vbus;
40 unsigned long ref_rate; 42 unsigned long ref_rate;
41 u32 ref_reg_val; 43 u32 ref_reg_val;
42 struct device *dev; 44 struct device *dev;