summaryrefslogtreecommitdiff
path: root/drivers/phy
diff options
context:
space:
mode:
authorSubhash Jadavani <subhashj@codeaurora.org>2014-10-29 19:20:13 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:01:07 -0700
commit2f94b8d7bdf854c76d5b0b6f70cd097dd80f19d7 (patch)
tree2debd7494d6e208ce5295530e9dc1db2d712b054 /drivers/phy
parentf76e7d00c79b66ac479c5fd8e33191705bc577f9 (diff)
scsi: ufs-qcom: add device ref_clk pad regulator voting support
UFS device's phy ref_clk is sourced via MSM's ref_clk pad. This pad is having its own power domain which is powered by 1.2v rail. This change adds the voting support for this pad rail. Change-Id: I179b2b9bb7ef2e7938ba0aaa87faed09cdad6139 Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> [venkatg@codeaurora.org: dropped ufs-qcom.h and include/linux/phy/phy-qcom-ufs.h changes] Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
Diffstat (limited to 'drivers/phy')
-rw-r--r--drivers/phy/phy-qcom-ufs.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c
index d3574c20d9ee..dc823f52e586 100644
--- a/drivers/phy/phy-qcom-ufs.c
+++ b/drivers/phy/phy-qcom-ufs.c
@@ -232,12 +232,19 @@ ufs_qcom_phy_init_vregulators(struct phy *generic_phy,
err = ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vdda_phy,
"vdda-phy");
+
+ if (err)
+ goto out;
+
+ /* vddp-ref-clk-* properties are optional */
+ __ufs_qcom_phy_init_vreg(generic_phy, &phy_common->vddp_ref_clk,
+ "vddp-ref-clk", true);
out:
return err;
}
-int ufs_qcom_phy_init_vreg(struct phy *phy,
- struct ufs_qcom_phy_vreg *vreg, const char *name)
+static int __ufs_qcom_phy_init_vreg(struct phy *phy,
+ struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional)
{
int err = 0;
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy);
@@ -254,7 +261,9 @@ int ufs_qcom_phy_init_vreg(struct phy *phy,
vreg->reg = devm_regulator_get(dev, name);
if (IS_ERR(vreg->reg)) {
err = PTR_ERR(vreg->reg);
- dev_err(dev, "failed to get %s, %d\n", name, err);
+ vreg->reg = NULL;
+ if (!optional)
+ dev_err(dev, "failed to get %s, %d\n", name, err);
goto out;
}
@@ -274,6 +283,11 @@ int ufs_qcom_phy_init_vreg(struct phy *phy,
}
err = 0;
}
+ snprintf(prop_name, MAX_PROP_NAME, "%s-always-on", name);
+ if (of_get_property(dev->of_node, prop_name, NULL))
+ vreg->is_always_on = true;
+ else
+ vreg->is_always_on = false;
}
if (!strcmp(name, "vdda-pll")) {
@@ -282,6 +296,9 @@ int ufs_qcom_phy_init_vreg(struct phy *phy,
} else if (!strcmp(name, "vdda-phy")) {
vreg->max_uV = VDDA_PHY_MAX_UV;
vreg->min_uV = VDDA_PHY_MIN_UV;
+ } else if (!strcmp(name, "vddp-ref-clk")) {
+ vreg->max_uV = VDDP_REF_CLK_MAX_UV;
+ vreg->min_uV = VDDP_REF_CLK_MIN_UV;
}
out:
@@ -425,7 +442,7 @@ int ufs_qcom_phy_disable_vreg(struct phy *phy,
struct device *dev = ufs_qcom_phy->dev;
int ret = 0;
- if (!vreg || !vreg->enabled)
+ if (!vreg || !vreg->enabled || vreg->is_always_on)
goto out;
ret = regulator_disable(vreg->reg);
@@ -643,9 +660,22 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
goto out_disable_pll;
}
+ /* enable device PHY ref_clk pad rail */
+ if (phy_common->vddp_ref_clk.reg) {
+ err = ufs_qcom_phy_enable_vreg(generic_phy,
+ &phy_common->vddp_ref_clk);
+ if (err) {
+ dev_err(dev, "%s enable vddp_ref_clk failed, err=%d\n",
+ __func__, err);
+ goto out_disable_ref_clk;
+ }
+ }
+
phy_common->is_powered_on = true;
goto out;
+out_disable_ref_clk:
+ ufs_qcom_phy_disable_ref_clk(generic_phy);
out_disable_pll:
ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_pll);
out_disable_phy:
@@ -660,6 +690,9 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy)
phy_common->phy_spec_ops->power_control(phy_common, false);
+ if (phy_common->vddp_ref_clk.reg)
+ ufs_qcom_phy_disable_vreg(generic_phy,
+ &phy_common->vddp_ref_clk);
ufs_qcom_phy_disable_ref_clk(generic_phy);
ufs_qcom_phy_disable_vreg(generic_phy, &phy_common->vdda_pll);