aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy/qualcomm/phy-qcom-ufs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/phy/qualcomm/phy-qcom-ufs.c')
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ufs.c57
1 files changed, 41 insertions, 16 deletions
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs.c b/drivers/phy/qualcomm/phy-qcom-ufs.c
index 78c339b2fc8b..45404e31e672 100644
--- a/drivers/phy/qualcomm/phy-qcom-ufs.c
+++ b/drivers/phy/qualcomm/phy-qcom-ufs.c
@@ -147,6 +147,21 @@ out:
147} 147}
148EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe); 148EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe);
149 149
150static int ufs_qcom_phy_get_reset(struct ufs_qcom_phy *phy_common)
151{
152 struct reset_control *reset;
153
154 if (phy_common->ufs_reset)
155 return 0;
156
157 reset = devm_reset_control_get_exclusive_by_index(phy_common->dev, 0);
158 if (IS_ERR(reset))
159 return PTR_ERR(reset);
160
161 phy_common->ufs_reset = reset;
162 return 0;
163}
164
150static int __ufs_qcom_phy_clk_get(struct device *dev, 165static int __ufs_qcom_phy_clk_get(struct device *dev,
151 const char *name, struct clk **clk_out, bool err_print) 166 const char *name, struct clk **clk_out, bool err_print)
152{ 167{
@@ -528,23 +543,38 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
528{ 543{
529 struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); 544 struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
530 struct device *dev = phy_common->dev; 545 struct device *dev = phy_common->dev;
546 bool is_rate_B = false;
531 int err; 547 int err;
532 548
533 if (phy_common->is_powered_on) 549 err = ufs_qcom_phy_get_reset(phy_common);
534 return 0; 550 if (err)
551 return err;
535 552
536 if (!phy_common->is_started) { 553 err = reset_control_assert(phy_common->ufs_reset);
537 err = ufs_qcom_phy_start_serdes(phy_common); 554 if (err)
538 if (err) 555 return err;
539 return err;
540 556
541 err = ufs_qcom_phy_is_pcs_ready(phy_common); 557 if (phy_common->mode == PHY_MODE_UFS_HS_B)
542 if (err) 558 is_rate_B = true;
543 return err;
544 559
545 phy_common->is_started = true; 560 err = phy_common->phy_spec_ops->calibrate(phy_common, is_rate_B);
561 if (err)
562 return err;
563
564 err = reset_control_deassert(phy_common->ufs_reset);
565 if (err) {
566 dev_err(dev, "Failed to assert UFS PHY reset");
567 return err;
546 } 568 }
547 569
570 err = ufs_qcom_phy_start_serdes(phy_common);
571 if (err)
572 return err;
573
574 err = ufs_qcom_phy_is_pcs_ready(phy_common);
575 if (err)
576 return err;
577
548 err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_phy); 578 err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_phy);
549 if (err) { 579 if (err) {
550 dev_err(dev, "%s enable vdda_phy failed, err=%d\n", 580 dev_err(dev, "%s enable vdda_phy failed, err=%d\n",
@@ -587,7 +617,6 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
587 } 617 }
588 } 618 }
589 619
590 phy_common->is_powered_on = true;
591 goto out; 620 goto out;
592 621
593out_disable_ref_clk: 622out_disable_ref_clk:
@@ -607,9 +636,6 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy)
607{ 636{
608 struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); 637 struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
609 638
610 if (!phy_common->is_powered_on)
611 return 0;
612
613 phy_common->phy_spec_ops->power_control(phy_common, false); 639 phy_common->phy_spec_ops->power_control(phy_common, false);
614 640
615 if (phy_common->vddp_ref_clk.reg) 641 if (phy_common->vddp_ref_clk.reg)
@@ -620,8 +646,7 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy)
620 646
621 ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_pll); 647 ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_pll);
622 ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_phy); 648 ufs_qcom_phy_disable_vreg(phy_common->dev, &phy_common->vdda_phy);
623 phy_common->is_powered_on = false; 649 reset_control_assert(phy_common->ufs_reset);
624
625 return 0; 650 return 0;
626} 651}
627EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off); 652EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off);