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

Commit d7fd00e4 authored by Bao D. Nguyen's avatar Bao D. Nguyen Committed by Gerrit - the friendly Code Review server
Browse files

scsi: ufs: add support for low voltage VCC support



Both UFS3.0 and higher version of ufs device are capable of running
at lower level (2.5v) of VCC rail. If both host and device supports
2.5v level then we do runtime switch of UFS VCC voltage level.

Change-Id: I6fea6c354cde5f7bd9d2a8a275c66e842726d358
Signed-off-by: default avatarBao D. Nguyen <nguyenb@codeaurora.org>
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: default avatarNitin Rawat <nitirawa@codeaurora.org>
parent 29371146
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -179,6 +179,10 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name,
				vreg->min_uV = be32_to_cpup(&prop[0]);
				vreg->max_uV = be32_to_cpup(&prop[1]);
			}
 #if defined(CONFIG_SCSI_UFSHCD_QTI)
			if (of_property_read_bool(np, "vcc-low-voltage-sup"))
				vreg->low_voltage_sup = true;
 #endif
		}
	} else if (!strcmp(name, "vccq")) {
		vreg->min_uV = UFS_VREG_VCCQ_MIN_UV;
+50 −1
Original line number Diff line number Diff line
@@ -287,7 +287,14 @@ static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba);
int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable);
static int ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set);
static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable);

#if defined(CONFIG_SCSI_UFSHCD_QTI)
static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
				enum ufs_dev_pwr_mode pwr_mode);
static int ufshcd_config_vreg(struct device *dev,
				struct ufs_vreg *vreg, bool on);
static int ufshcd_enable_vreg(struct device *dev, struct ufs_vreg *vreg);
static int ufshcd_disable_vreg(struct device *dev, struct ufs_vreg *vreg);
#endif
static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
{
	return tag >= 0 && tag < hba->nutrs;
@@ -7152,6 +7159,40 @@ static inline void ufshcd_blk_pm_runtime_init(struct scsi_device *sdev)
	scsi_autopm_put_device(sdev);
}

 #if defined(CONFIG_SCSI_UFSHCD_QTI)
static int ufshcd_set_low_vcc_level(struct ufs_hba *hba)
{
	int ret;
	struct ufs_vreg *vreg = hba->vreg_info.vcc;

	/* Check if device supports the low voltage VCC feature */
	if (hba->dev_info.wspecversion < 0x300)
		return 0;
	/*
	 * Check if host has support for low VCC voltage?
	 * In addition, also check if we have already set the low VCC level
	 * or not?
	 */
	if (!vreg->low_voltage_sup || vreg->low_voltage_active)
		return 0;

	/* Put the device in sleep before lowering VCC level */
	ret = ufshcd_set_dev_pwr_mode(hba, UFS_SLEEP_PWR_MODE);

	/* Switch off VCC before switching it ON at 2.5v */
	ret = ufshcd_disable_vreg(hba->dev, vreg);
	/* add ~2ms delay before renabling VCC at lower voltage */
	usleep_range(2000, 2100);
	/* Now turn back VCC ON at low voltage */
	vreg->low_voltage_active = true;
	ret = ufshcd_enable_vreg(hba->dev, vreg);

	/* Bring the device in active now */
	ret = ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE);

	return ret;
}
#endif
/**
 * ufshcd_scsi_add_wlus - Adds required W-LUs
 * @hba: per-adapter instance
@@ -7711,6 +7752,10 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
	if (ret)
		goto out;

#if defined(CONFIG_SCSI_UFSHCD_QTI)
	ufshcd_set_low_vcc_level(hba);
#endif

	/* Initialize devfreq after UFS device is detected */
	if (ufshcd_is_clkscaling_supported(hba)) {
		memcpy(&hba->clk_scaling.saved_pwr_info.info,
@@ -8011,6 +8056,10 @@ static int ufshcd_config_vreg(struct device *dev,

		if (vreg->min_uV && vreg->max_uV) {
			min_uV = on ? vreg->min_uV : 0;
#if defined(CONFIG_SCSI_UFSHCD_QTI)
			if (vreg->low_voltage_sup && !vreg->low_voltage_active && on)
				min_uV = vreg->max_uV;
#endif
			ret = regulator_set_voltage(reg, min_uV, vreg->max_uV);
			if (ret) {
				dev_err(dev,