Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d26d851 authored by Nitin Rawat's avatar Nitin Rawat
Browse files

scsi: ufs: Add load voting for UFS's VCCQ2 parent regulator



The UFS clock gating events can trigger CX Power Collapse followed by
SoC system sleep events, independent of the Linux Power Management's
runtime/system suspend events. When this happens, the VCCQ2's
parent regulator source may limit the amount of current the UFS VCCQ
regulator can draw while the SoC is in sleep mode but the UFS device
is in active full power mode. The UFS3.0 and later devices with
Turbo Write feature support may consume high power during the
cache flush and bkops operations which may trigger over current
detection event. To prevent the VCCQ2's parent regulator source
from limiting the VCCQ's regulator power consumption while the
UFS device is in active mode, add a high load voting on
the VCCQ parent regulator. Set the low load voting on this
regulator when the UFS enters Linux's runtime/system suspend.
In addition, vote the UFS regulator sources in fully active mode when
the UFS bkops is enabled during runtime suspend.

Change-Id: I5e66d60ad7459b65bd45b502afbfe569602e8a68
Signed-off-by: default avatarNitin Rawat <quic_nitirawa@quicinc.com>
parent a9ffd259
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -858,6 +858,10 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
			ufs_qcom_config_vreg(hba->dev,
					host->vccq_parent, false);

		if (host->vccq2_parent && !hba->auto_bkops_enabled)
			ufs_qcom_config_vreg(hba->dev,
					host->vccq2_parent, false);

		if (ufs_qcom_is_link_off(hba)) {
			/* Assert PHY soft reset */
			ufs_qcom_assert_reset(hba);
@@ -897,6 +901,9 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
	if (host->vccq_parent)
		ufs_qcom_config_vreg(hba->dev, host->vccq_parent, true);

	if (host->vccq2_parent)
		ufs_qcom_config_vreg(hba->dev, host->vccq2_parent, true);

	err = ufs_qcom_enable_lane_clks(host);
	if (err)
		goto out;
@@ -2077,6 +2084,8 @@ static int ufs_qcom_parse_reg_info(struct ufs_qcom_host *host, char *name,
			vreg->min_uV = VDDP_REF_CLK_MIN_UV;
		else if (!strcmp(name, "qcom,vccq-parent"))
			vreg->min_uV = 0;
		else if (!strcmp(name, "qcom,vccq2-parent"))
			vreg->min_uV = 0;
		ret = 0;
	}

@@ -2089,6 +2098,8 @@ static int ufs_qcom_parse_reg_info(struct ufs_qcom_host *host, char *name,
			vreg->max_uV = VDDP_REF_CLK_MAX_UV;
		else if (!strcmp(name, "qcom,vccq-parent"))
			vreg->max_uV = 0;
		else if (!strcmp(name, "qcom,vccq2-parent"))
			vreg->max_uV = 0;
		ret = 0;
	}

@@ -2236,6 +2247,17 @@ static int ufs_qcom_init(struct ufs_hba *hba)
		}
	}

	err = ufs_qcom_parse_reg_info(host, "qcom,vccq2-parent",
				      &host->vccq2_parent);
	if (host->vccq2_parent) {
		err = ufs_qcom_config_vreg(hba->dev, host->vccq2_parent, true);
		if (err) {
			dev_err(dev, "%s: failed vccq2-parent set load: %d\n",
				__func__, err);
			goto out_disable_vddp;
		}
	}

	err = ufs_qcom_init_lane_clks(host);
	if (err)
		goto out_set_load_vccq_parent;
@@ -2268,6 +2290,8 @@ static int ufs_qcom_init(struct ufs_hba *hba)
out_set_load_vccq_parent:
	if (host->vccq_parent)
		ufs_qcom_config_vreg(hba->dev, host->vccq_parent, false);
	if (host->vccq2_parent)
		ufs_qcom_config_vreg(hba->dev, host->vccq2_parent, false);
out_disable_vddp:
	if (host->vddp_ref_clk)
		ufs_qcom_disable_vreg(dev, host->vddp_ref_clk);
+1 −0
Original line number Diff line number Diff line
@@ -363,6 +363,7 @@ struct ufs_qcom_host {
	struct request *req_pending;
	struct ufs_vreg *vddp_ref_clk;
	struct ufs_vreg *vccq_parent;
	struct ufs_vreg *vccq2_parent;
	bool work_pending;
	bool is_phy_pwr_on;
	bool err_occurred;