diff options
Diffstat (limited to 'drivers/scsi/ufs/ufs-qcom.c')
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom.c | 39 |
1 files changed, 16 insertions, 23 deletions
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 3aedf73f1131..aa43bfea0d00 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1094,10 +1094,12 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba) * ufs_qcom_setup_clocks - enables/disable clocks * @hba: host controller instance * @on: If true, enable clocks else disable them. + * @status: PRE_CHANGE or POST_CHANGE notify * * Returns 0 on success, non-zero on failure. */ -static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) +static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, + enum ufs_notify_change_status status) { struct ufs_qcom_host *host = ufshcd_get_variant(hba); int err; @@ -1111,18 +1113,9 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) if (!host) return 0; - if (on) { - err = ufs_qcom_phy_enable_iface_clk(host->generic_phy); - if (err) - goto out; + if (on && (status == POST_CHANGE)) { + phy_power_on(host->generic_phy); - err = ufs_qcom_phy_enable_ref_clk(host->generic_phy); - if (err) { - dev_err(hba->dev, "%s enable phy ref clock failed, err=%d\n", - __func__, err); - ufs_qcom_phy_disable_iface_clk(host->generic_phy); - goto out; - } /* enable the device ref clock for HS mode*/ if (ufshcd_is_hs_mode(&hba->pwr_info)) ufs_qcom_dev_ref_clk_ctrl(host, true); @@ -1130,14 +1123,15 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) if (vote == host->bus_vote.min_bw_vote) ufs_qcom_update_bus_bw_vote(host); - } else { - - /* M-PHY RMMI interface clocks can be turned off */ - ufs_qcom_phy_disable_iface_clk(host->generic_phy); - if (!ufs_qcom_is_link_active(hba)) + } else if (!on && (status == PRE_CHANGE)) { + if (!ufs_qcom_is_link_active(hba)) { /* disable device ref_clk */ ufs_qcom_dev_ref_clk_ctrl(host, false); + /* powering off PHY during aggressive clk gating */ + phy_power_off(host->generic_phy); + } + vote = host->bus_vote.min_bw_vote; } @@ -1146,7 +1140,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on) dev_err(hba->dev, "%s: set bus vote failed %d\n", __func__, err); -out: return err; } @@ -1204,12 +1197,12 @@ static int ufs_qcom_init(struct ufs_hba *hba) if (IS_ERR(host->generic_phy)) { err = PTR_ERR(host->generic_phy); dev_err(dev, "%s: PHY get failed %d\n", __func__, err); - goto out; + goto out_variant_clear; } err = ufs_qcom_bus_register(host); if (err) - goto out_host_free; + goto out_variant_clear; ufs_qcom_get_controller_revision(hba, &host->hw_ver.major, &host->hw_ver.minor, &host->hw_ver.step); @@ -1254,7 +1247,7 @@ static int ufs_qcom_init(struct ufs_hba *hba) ufs_qcom_set_caps(hba); ufs_qcom_advertise_quirks(hba); - ufs_qcom_setup_clocks(hba, true); + ufs_qcom_setup_clocks(hba, true, POST_CHANGE); if (hba->dev->id < MAX_UFS_QCOM_HOSTS) ufs_qcom_hosts[hba->dev->id] = host; @@ -1274,8 +1267,7 @@ out_disable_phy: phy_power_off(host->generic_phy); out_unregister_bus: phy_exit(host->generic_phy); -out_host_free: - devm_kfree(dev, host); +out_variant_clear: ufshcd_set_variant(hba, NULL); out: return err; @@ -1287,6 +1279,7 @@ static void ufs_qcom_exit(struct ufs_hba *hba) ufs_qcom_disable_lane_clks(host); phy_power_off(host->generic_phy); + phy_exit(host->generic_phy); } static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba, |