diff options
Diffstat (limited to 'drivers/phy/qualcomm/phy-qcom-ufs.c')
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-ufs.c | 57 |
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 | } |
148 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe); | 148 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe); |
149 | 149 | ||
150 | static 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 | |||
150 | static int __ufs_qcom_phy_clk_get(struct device *dev, | 165 | static 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 | ||
593 | out_disable_ref_clk: | 622 | out_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 | } |
627 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off); | 652 | EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off); |