Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Marek Szyprowski and committed by
Kishon Vijay Abraham I
a007ddba 6ff33f39

+28 -2
+3
Documentation/devicetree/bindings/phy/samsung-phy.txt
··· 44 44 - the "ref" clock is used to get the rate of the clock provided to the 45 45 PHY module 46 46 47 + Optional properties: 48 + - vbus-supply: power-supply phandle for vbus power source 49 + 47 50 The first phandle argument in the PHY specifier identifies the PHY, its 48 51 meaning is compatible dependent. For the currently supported SoCs (Exynos 4210 49 52 and Exynos 4212) it is as follows:
+23 -2
drivers/phy/phy-samsung-usb2.c
··· 27 27 28 28 dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n", 29 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 37 ret = clk_prepare_enable(drv->clk); 31 38 if (ret) 32 39 goto err_main_clk; ··· 55 48 err_instance_clk: 56 49 clk_disable_unprepare(drv->clk); 57 50 err_main_clk: 51 + if (drv->vbus) 52 + regulator_disable(drv->vbus); 53 + err_regulator: 58 54 return ret; 59 55 } 60 56 ··· 65 55 { 66 56 struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy); 67 57 struct samsung_usb2_phy_driver *drv = inst->drv; 68 - int ret; 58 + int ret = 0; 69 59 70 60 dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n", 71 61 inst->cfg->label); ··· 78 68 } 79 69 clk_disable_unprepare(drv->ref_clk); 80 70 clk_disable_unprepare(drv->clk); 81 - return 0; 71 + if (drv->vbus) 72 + ret = regulator_disable(drv->vbus); 73 + 74 + return ret; 82 75 } 83 76 84 77 static const struct phy_ops samsung_usb2_phy_ops = { ··· 214 201 ret = drv->cfg->rate_to_clk(drv->ref_rate, &drv->ref_reg_val); 215 202 if (ret) 216 203 return ret; 204 + } 205 + 206 + drv->vbus = devm_regulator_get(dev, "vbus"); 207 + if (IS_ERR(drv->vbus)) { 208 + ret = PTR_ERR(drv->vbus); 209 + if (ret == -EPROBE_DEFER) 210 + return ret; 211 + drv->vbus = NULL; 217 212 } 218 213 219 214 for (i = 0; i < drv->cfg->num_phys; i++) {
+2
drivers/phy/phy-samsung-usb2.h
··· 17 17 #include <linux/device.h> 18 18 #include <linux/regmap.h> 19 19 #include <linux/spinlock.h> 20 + #include <linux/regulator/consumer.h> 20 21 21 22 #define KHZ 1000 22 23 #define MHZ (KHZ * KHZ) ··· 38 37 const struct samsung_usb2_phy_config *cfg; 39 38 struct clk *clk; 40 39 struct clk *ref_clk; 40 + struct regulator *vbus; 41 41 unsigned long ref_rate; 42 42 u32 ref_reg_val; 43 43 struct device *dev;