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

Commit 2d3c8712 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "scsi: ufs: Add support for turning off UFS power supplies"

parents a34a50ab ed2d1adb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -535,6 +535,7 @@ struct ufs_vreg {
	int max_uV;
	bool low_voltage_sup;
	bool low_voltage_active;
	bool sys_suspend_pwr_off;
	int min_uA;
	int max_uA;
};
+15 −0
Original line number Diff line number Diff line
@@ -217,9 +217,24 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name,
	} else if (!strcmp(name, "vccq")) {
		vreg->min_uV = UFS_VREG_VCCQ_MIN_UV;
		vreg->max_uV = UFS_VREG_VCCQ_MAX_UV;
		/**
		 * Only if the SoC supports turning off VCCQ or VCCQ2 power
		 * supply source during power collapse, set a flag to turn off
		 * the specified power supply to reduce the system power
		 * consumption during system suspend events. The tradeoffs are:
		 *   - System resume time will increase due
		 *     to UFS device full re-initialization time.
		 *   - UFS device life may be affected due to multiple
		 *     UFS power on/off events.
		 * The benefits vs tradeoff should be considered carefully.
		 */
		if (of_property_read_bool(np, "vccq-pwr-collapse-sup"))
			vreg->sys_suspend_pwr_off = true;
	} else if (!strcmp(name, "vccq2")) {
		vreg->min_uV = UFS_VREG_VCCQ2_MIN_UV;
		vreg->max_uV = UFS_VREG_VCCQ2_MAX_UV;
		if (of_property_read_bool(np, "vccq2-pwr-collapse-sup"))
			vreg->sys_suspend_pwr_off = true;
	}

	goto out;
+55 −9
Original line number Diff line number Diff line
@@ -8864,6 +8864,22 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
			goto out;
	}

	/**
	 * UFS3.0 and newer devices use Vcc and Vccq(1.2V)
	 * while UFS2.1 devices use Vcc and Vccq2(1.8V) power
	 * supplies. If the system allows turning off the regulators
	 * during power collapse event, turn off the regulators
	 * during system suspend events. This will cause the UFS
	 * device to re-initialize upon system resume events.
	 */
	if ((hba->dev_info.w_spec_version >= 0x300 &&
		hba->vreg_info.vccq->sys_suspend_pwr_off) ||
		(hba->dev_info.w_spec_version < 0x300 &&
		hba->vreg_info.vccq2->sys_suspend_pwr_off))
		hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state(
				UFS_POWERDOWN_PWR_MODE,
				UIC_LINK_OFF_STATE);

	/* UFS device is also active now */
	ufshcd_set_ufs_dev_active(hba);
	ufshcd_force_reset_auto_bkops(hba);
@@ -10109,7 +10125,20 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
	 */
	if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) &&
	    !hba->dev_info.is_lu_power_on_wp) {
		ufshcd_setup_vreg(hba, false);
		ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
		if (hba->dev_info.w_spec_version >= 0x300 &&
			hba->vreg_info.vccq->sys_suspend_pwr_off)
			ufshcd_toggle_vreg(hba->dev,
				hba->vreg_info.vccq, false);
		else
			ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);

		if (hba->dev_info.w_spec_version < 0x300 &&
			hba->vreg_info.vccq2->sys_suspend_pwr_off)
			ufshcd_toggle_vreg(hba->dev,
				hba->vreg_info.vccq2, false);
		else
			ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
	} else if (!ufshcd_is_ufs_dev_active(hba)) {
		ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
		if (!ufshcd_is_link_active(hba)) {
@@ -10125,22 +10154,39 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)

	if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) &&
		!hba->dev_info.is_lu_power_on_wp) {
		ret = ufshcd_setup_vreg(hba, true);
	} else if (!ufshcd_is_ufs_dev_active(hba)) {
		if (!ret && !ufshcd_is_link_active(hba)) {
			ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq);
		if (hba->dev_info.w_spec_version < 0x300 &&
			hba->vreg_info.vccq2->sys_suspend_pwr_off)
			ret = ufshcd_toggle_vreg(hba->dev,
				hba->vreg_info.vccq2, true);
		else
			ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2);
		if (ret)
			goto vcc_disable;

		if (hba->dev_info.w_spec_version >= 0x300 &&
			hba->vreg_info.vccq->sys_suspend_pwr_off)
			ret = ufshcd_toggle_vreg(hba->dev,
				hba->vreg_info.vccq, true);
		else
			ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq);
		if (ret)
			goto vccq2_lpm;
		ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, true);
	} else if (!ufshcd_is_ufs_dev_active(hba)) {
		if (!ufshcd_is_link_active(hba)) {
			ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2);
			if (ret)
				goto vccq_lpm;
				goto vcc_disable;
			ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq);
			if (ret)
				goto vccq2_lpm;
		}
		ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, true);
	}
	goto out;

vccq_lpm:
	ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);
vccq2_lpm:
	ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
vcc_disable:
	ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
out: