diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-09-02 13:52:53 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-09-02 13:52:53 -0700 |
| commit | a48893e20274b9f034349ebb886d55b488611deb (patch) | |
| tree | aeefc84e1a92625fa6e2a9132cf0c8bff5a3de85 | |
| parent | 8965988fffb2b7425afcc50d49e9a171ced0df46 (diff) | |
| parent | d72551997664fb9d50babf5597039d7a8883afe9 (diff) | |
Merge "usb: phy: handle phy related regulators properly"
| -rw-r--r-- | drivers/usb/phy/phy-msm-ssusb-qmp.c | 108 |
1 files changed, 49 insertions, 59 deletions
diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c index 529e4ea76a96..87235a5a4f99 100644 --- a/drivers/usb/phy/phy-msm-ssusb-qmp.c +++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c @@ -89,6 +89,7 @@ struct msm_ssphy_qmp { struct clk *pipe_clk; struct clk *phy_reset; struct clk *phy_phy_reset; + bool power_enabled; bool clk_enabled; bool cable_connected; bool in_suspend; @@ -159,38 +160,47 @@ static void msm_ssusb_qmp_enable_autonomous(struct msm_ssphy_qmp *phy, } } - -static int msm_ssusb_qmp_config_vdd(struct msm_ssphy_qmp *phy, int high) +static int msm_ssusb_qmp_ldo_enable(struct msm_ssphy_qmp *phy, int on) { - int min, ret; + int min, rc = 0; - min = high ? 1 : 0; /* low or none? */ - ret = regulator_set_voltage(phy->vdd, phy->vdd_levels[min], - phy->vdd_levels[2]); - if (ret) { - dev_err(phy->phy.dev, "unable to set voltage for ssusb vdd\n"); - return ret; - } + dev_dbg(phy->phy.dev, "reg (%s)\n", on ? "HPM" : "LPM"); - dev_dbg(phy->phy.dev, "min_vol:%d max_vol:%d\n", - phy->vdd_levels[min], phy->vdd_levels[2]); - return ret; -} + if (phy->power_enabled == on) { + dev_dbg(phy->phy.dev, "PHYs' regulators status %d\n", + phy->power_enabled); + return 0; + } -static int msm_ssusb_qmp_ldo_enable(struct msm_ssphy_qmp *phy, int on) -{ - int rc = 0; + phy->power_enabled = on; - dev_dbg(phy->phy.dev, "reg (%s)\n", on ? "HPM" : "LPM"); + min = on ? 1 : 0; /* low or none? */ if (!on) goto disable_regulators; + rc = regulator_set_voltage(phy->vdd, phy->vdd_levels[min], + phy->vdd_levels[2]); + if (rc) { + dev_err(phy->phy.dev, "unable to set voltage for ssusb vdd\n"); + return rc; + } + + dev_dbg(phy->phy.dev, "min_vol:%d max_vol:%d\n", + phy->vdd_levels[min], phy->vdd_levels[2]); + + rc = regulator_enable(phy->vdd); + if (rc) { + dev_err(phy->phy.dev, + "regulator_enable(phy->vdd) failed, ret=%d", + rc); + goto unconfig_vdd; + } rc = regulator_set_load(phy->core_ldo, USB_SSPHY_HPM_LOAD); if (rc < 0) { dev_err(phy->phy.dev, "Unable to set HPM of core_ldo\n"); - return rc; + goto disable_vdd; } rc = regulator_set_voltage(phy->core_ldo, @@ -226,6 +236,18 @@ put_core_ldo_lpm: if (rc < 0) dev_err(phy->phy.dev, "Unable to set LPM of core_ldo\n"); +disable_vdd: + rc = regulator_disable(phy->vdd); + if (rc) + dev_err(phy->phy.dev, "regulator_disable(phy->vdd) failed, ret=%d", + rc); + +unconfig_vdd: + rc = regulator_set_voltage(phy->vdd, phy->vdd_levels[min], + phy->vdd_levels[2]); + if (rc) + dev_err(phy->phy.dev, "unable to set voltage for ssusb vdd\n"); + return rc < 0 ? rc : 0; } @@ -263,6 +285,14 @@ static int msm_ssphy_qmp_init(struct usb_phy *uphy) if (phy->emulation) return 0; + ret = msm_ssusb_qmp_ldo_enable(phy, 1); + if (ret) { + dev_err(phy->phy.dev, + "msm_ssusb_qmp_ldo_enable(1) failed, ret=%d\n", + ret); + return ret; + } + if (!phy->clk_enabled) { if (phy->ref_clk_src) clk_prepare_enable(phy->ref_clk_src); @@ -408,12 +438,6 @@ static int msm_ssphy_power_enable(struct msm_ssphy_qmp *phy, bool on) */ if (!host && !phy->cable_connected) { if (on) { - ret = regulator_enable(phy->vdd); - if (ret) - dev_err(phy->phy.dev, - "regulator_enable(phy->vdd) failed, ret=%d", - ret); - ret = msm_ssusb_qmp_ldo_enable(phy, 1); if (ret) dev_err(phy->phy.dev, @@ -425,11 +449,6 @@ static int msm_ssphy_power_enable(struct msm_ssphy_qmp *phy, bool on) dev_err(phy->phy.dev, "msm_ssusb_qmp_ldo_enable(0) failed, ret=%d\n", ret); - - ret = regulator_disable(phy->vdd); - if (ret) - dev_err(phy->phy.dev, "regulator_disable(phy->vdd) failed, ret=%d", - ret); } } @@ -733,24 +752,6 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev) goto err; } - ret = msm_ssusb_qmp_config_vdd(phy, 1); - if (ret) { - dev_err(dev, "ssusb vdd_dig configuration failed\n"); - goto err; - } - - ret = regulator_enable(phy->vdd); - if (ret) { - dev_err(dev, "unable to enable the ssusb vdd_dig\n"); - goto unconfig_ss_vdd; - } - - ret = msm_ssusb_qmp_ldo_enable(phy, 1); - if (ret) { - dev_err(dev, "ssusb vreg enable failed\n"); - goto disable_ss_vdd; - } - phy->ref_clk_src = devm_clk_get(dev, "ref_clk_src"); if (IS_ERR(phy->ref_clk_src)) phy->ref_clk_src = NULL; @@ -772,16 +773,7 @@ static int msm_ssphy_qmp_probe(struct platform_device *pdev) phy->phy.type = USB_PHY_TYPE_USB3; ret = usb_add_phy_dev(&phy->phy); - if (ret) - goto disable_ss_ldo; - return 0; -disable_ss_ldo: - msm_ssusb_qmp_ldo_enable(phy, 0); -disable_ss_vdd: - regulator_disable(phy->vdd); -unconfig_ss_vdd: - msm_ssusb_qmp_config_vdd(phy, 0); err: return ret; } @@ -799,8 +791,6 @@ static int msm_ssphy_qmp_remove(struct platform_device *pdev) if (phy->ref_clk_src) clk_disable_unprepare(phy->ref_clk_src); msm_ssusb_qmp_ldo_enable(phy, 0); - regulator_disable(phy->vdd); - msm_ssusb_qmp_config_vdd(phy, 0); clk_disable_unprepare(phy->aux_clk); clk_disable_unprepare(phy->cfg_ahb_clk); clk_disable_unprepare(phy->pipe_clk); |
